doppelganger detection walltime refactor (#2656)
* strawman doppelganger detection walltime refactor * move DoppelgangerProtection to Eth2Processor * increase comment precision * document difference between broadcastStartEpoch and nodeLaunchSlot, and allow for one-slot overlap to avoid false positives on intra-slot restarts
This commit is contained in:
parent
53d05060c9
commit
87ed9e62a1
|
@ -45,6 +45,18 @@ declareHistogram beacon_block_delay,
|
||||||
"Time(s) between slot start and beacon block reception", buckets = delayBuckets
|
"Time(s) between slot start and beacon block reception", buckets = delayBuckets
|
||||||
|
|
||||||
type
|
type
|
||||||
|
DoppelgangerProtection = object
|
||||||
|
broadcastStartEpoch*: Epoch ##\
|
||||||
|
## Set anew, each time gossip is re-enabled after syncing completes, so
|
||||||
|
## might reset multiple times per instance. This allows some safe level
|
||||||
|
## of gossip interleaving between nodes so long as they don't gossip at
|
||||||
|
## the same time.
|
||||||
|
|
||||||
|
nodeLaunchSlot: Slot ##\
|
||||||
|
## Set once, at node launch. This functions as a basic protection against
|
||||||
|
## false positives from attestations persisting within the gossip network
|
||||||
|
## across quick restarts.
|
||||||
|
|
||||||
Eth2Processor* = object
|
Eth2Processor* = object
|
||||||
doppelGangerDetectionEnabled*: bool
|
doppelGangerDetectionEnabled*: bool
|
||||||
getWallTime*: GetWallTimeFn
|
getWallTime*: GetWallTimeFn
|
||||||
|
@ -88,6 +100,8 @@ proc new*(T: type Eth2Processor,
|
||||||
getWallTime: GetWallTimeFn): ref Eth2Processor =
|
getWallTime: GetWallTimeFn): ref Eth2Processor =
|
||||||
(ref Eth2Processor)(
|
(ref Eth2Processor)(
|
||||||
doppelGangerDetectionEnabled: doppelGangerDetectionEnabled,
|
doppelGangerDetectionEnabled: doppelGangerDetectionEnabled,
|
||||||
|
doppelgangerDetection: DoppelgangerProtection(
|
||||||
|
nodeLaunchSlot: getWallTime().slotOrZero),
|
||||||
getWallTime: getWallTime,
|
getWallTime: getWallTime,
|
||||||
blockProcessor: blockProcessor,
|
blockProcessor: blockProcessor,
|
||||||
dag: dag,
|
dag: dag,
|
||||||
|
@ -158,15 +172,15 @@ proc blockValidator*(
|
||||||
|
|
||||||
proc checkForPotentialDoppelganger(
|
proc checkForPotentialDoppelganger(
|
||||||
self: var Eth2Processor, attestation: Attestation,
|
self: var Eth2Processor, attestation: Attestation,
|
||||||
attesterIndices: openArray[ValidatorIndex], wallSlot: Slot) =
|
attesterIndices: openArray[ValidatorIndex]) =
|
||||||
let epoch = wallSlot.epoch
|
# Only check for attestations after node launch. There might be one slot of
|
||||||
|
# overlap in quick intra-slot restarts so trade off a few true negatives in
|
||||||
# Only check for current epoch, not potential attestations bouncing around
|
# the service of avoiding more likely false positives.
|
||||||
# from up to several minutes prior.
|
if attestation.data.slot <= self.doppelgangerDetection.nodeLaunchSlot + 1:
|
||||||
if attestation.data.slot.epoch < epoch:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if epoch < self.doppelgangerDetection.broadcastStartEpoch:
|
if attestation.data.slot.epoch <
|
||||||
|
self.doppelgangerDetection.broadcastStartEpoch:
|
||||||
let tgtBlck = self.dag.getRef(attestation.data.target.root)
|
let tgtBlck = self.dag.getRef(attestation.data.target.root)
|
||||||
doAssert not tgtBlck.isNil # because attestation is valid above
|
doAssert not tgtBlck.isNil # because attestation is valid above
|
||||||
|
|
||||||
|
@ -219,8 +233,7 @@ proc attestationValidator*(
|
||||||
|
|
||||||
let (attestation_index, sig) = v.get()
|
let (attestation_index, sig) = v.get()
|
||||||
|
|
||||||
self[].checkForPotentialDoppelganger(
|
self[].checkForPotentialDoppelganger(attestation, [attestation_index])
|
||||||
attestation, [attestation_index], wallSlot)
|
|
||||||
|
|
||||||
trace "Attestation validated"
|
trace "Attestation validated"
|
||||||
self.attestationPool[].addAttestation(
|
self.attestationPool[].addAttestation(
|
||||||
|
@ -267,8 +280,7 @@ proc aggregateValidator*(
|
||||||
let (attesting_indices, sig) = v.get()
|
let (attesting_indices, sig) = v.get()
|
||||||
|
|
||||||
self[].checkForPotentialDoppelganger(
|
self[].checkForPotentialDoppelganger(
|
||||||
signedAggregateAndProof.message.aggregate, attesting_indices,
|
signedAggregateAndProof.message.aggregate, attesting_indices)
|
||||||
wallSlot)
|
|
||||||
|
|
||||||
trace "Aggregate validated",
|
trace "Aggregate validated",
|
||||||
aggregator_index = signedAggregateAndProof.message.aggregator_index,
|
aggregator_index = signedAggregateAndProof.message.aggregator_index,
|
||||||
|
|
|
@ -470,9 +470,6 @@ type
|
||||||
current_justified_checkpoint*: Checkpoint
|
current_justified_checkpoint*: Checkpoint
|
||||||
finalized_checkpoint*: Checkpoint
|
finalized_checkpoint*: Checkpoint
|
||||||
|
|
||||||
DoppelgangerProtection* = object
|
|
||||||
broadcastStartEpoch*: Epoch
|
|
||||||
|
|
||||||
type
|
type
|
||||||
# Caches for computing justificiation, rewards and penalties - based on
|
# Caches for computing justificiation, rewards and penalties - based on
|
||||||
# implementation in Lighthouse:
|
# implementation in Lighthouse:
|
||||||
|
|
Loading…
Reference in New Issue