rename options and internal structures to doppelgangerFoo and remove probing
This commit is contained in:
parent
a3678d6bf0
commit
281853eee8
|
@ -51,7 +51,7 @@ type
|
|||
enabled = "Always enabled"
|
||||
disabled = "Always disabled"
|
||||
|
||||
GossipSlashingProtectionMode* {.pure.} = enum
|
||||
DoppelgangerProtectionMode* {.pure.} = enum
|
||||
dontcheck
|
||||
warn
|
||||
stop
|
||||
|
@ -260,11 +260,11 @@ type
|
|||
desc: "Write SSZ dumps of blocks, attestations and states to data dir"
|
||||
name: "dump" }: bool
|
||||
|
||||
gossipSlashingProtection* {.
|
||||
defaultValue: GossipSlashingProtectionMode.warn
|
||||
doppelgangerProtection* {.
|
||||
defaultValue: DoppelgangerProtectionMode.warn
|
||||
desc: "[=warn*|stop] What to do when another validator is detected to be running the same validator keys (default `warn`, will become `stop` in the future)"
|
||||
name: "gossip-slashing-protection"
|
||||
}: GossipSlashingProtectionMode
|
||||
name: "doppelganger-protection"
|
||||
}: DoppelgangerProtectionMode
|
||||
|
||||
of createTestnet:
|
||||
testnetDepositsFile* {.
|
||||
|
|
|
@ -78,7 +78,7 @@ type
|
|||
attestationsQueue*: AsyncQueue[AttestationEntry]
|
||||
aggregatesQueue*: AsyncQueue[AggregateEntry]
|
||||
|
||||
gossipSlashingProtection*: DupProtection
|
||||
doppelgangerProtection*: DoppelgangerProtection
|
||||
|
||||
proc updateHead*(self: var Eth2Processor, wallSlot: Slot) =
|
||||
## Trigger fork choice and returns the new head block.
|
||||
|
@ -304,7 +304,7 @@ proc blockValidator*(
|
|||
|
||||
{.push raises: [Defect].}
|
||||
|
||||
proc checkForPotentialSelfSlashing(
|
||||
proc checkForPotentialDoppelganger(
|
||||
self: var Eth2Processor, attestationData: AttestationData,
|
||||
attesterIndices: IntSet, wallSlot: Slot) =
|
||||
# Attestations remain valid for 32 slots, so avoid confusing with one's own
|
||||
|
@ -316,13 +316,9 @@ proc checkForPotentialSelfSlashing(
|
|||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/p2p-interface.md#configuration
|
||||
ATTESTATION_PROPAGATION_SLOT_RANGE = 32
|
||||
|
||||
GUARD_EPOCHS = ATTESTATION_PROPAGATION_SLOT_RANGE div SLOTS_PER_EPOCH
|
||||
|
||||
# If gossipSlashingProtection not dontcheck or stop, it's the default "warn".
|
||||
# If doppelgangerProtection not dontcheck or stop, it's the default "warn".
|
||||
let epoch = wallSlot.epoch
|
||||
if epoch < self.gossipSlashingProtection.broadcastStartEpoch and
|
||||
epoch >= self.gossipSlashingProtection.probeEpoch and
|
||||
epoch <= self.gossipSlashingProtection.probeEpoch + GUARD_EPOCHS:
|
||||
if epoch < self.doppelgangerProtection.broadcastStartEpoch:
|
||||
let tgtBlck = self.chainDag.getRef(attestationData.target.root)
|
||||
doAssert not tgtBlck.isNil # because attestation is valid above
|
||||
|
||||
|
@ -336,7 +332,7 @@ proc checkForPotentialSelfSlashing(
|
|||
validatorIndex,
|
||||
validatorPubkey
|
||||
beacon_duplicate_validator_protection_activated.inc()
|
||||
if self.config.gossipSlashingProtection == GossipSlashingProtectionMode.stop:
|
||||
if self.config.doppelgangerProtection == DoppelgangerProtectionMode.stop:
|
||||
warn "We believe you are currently running another instance of the same validator. We've disconnected you from the network as this presents a significant slashing risk. Possible next steps are (a) making sure you've disconnected your validator from your old machine before restarting the client; and (b) running the client again with the gossip-slashing-protection option disabled, only if you are absolutely sure this is the only instance of your validator running, and reporting the issue at https://github.com/status-im/nimbus-eth2/issues."
|
||||
quit QuitFailure
|
||||
|
||||
|
@ -371,7 +367,7 @@ proc attestationValidator*(
|
|||
beacon_attestations_received.inc()
|
||||
beacon_attestation_delay.observe(delay.toFloatSeconds())
|
||||
|
||||
self.checkForPotentialSelfSlashing(attestation.data, v.value, wallSlot)
|
||||
self.checkForPotentialDoppelganger(attestation.data, v.value, wallSlot)
|
||||
|
||||
while self.attestationsQueue.full():
|
||||
try:
|
||||
|
@ -425,7 +421,7 @@ proc aggregateValidator*(
|
|||
beacon_aggregates_received.inc()
|
||||
beacon_aggregate_delay.observe(delay.toFloatSeconds())
|
||||
|
||||
self.checkForPotentialSelfSlashing(
|
||||
self.checkForPotentialDoppelganger(
|
||||
signedAggregateAndProof.message.aggregate.data, v.value, wallSlot)
|
||||
|
||||
while self.aggregatesQueue.full():
|
||||
|
|
|
@ -695,44 +695,20 @@ proc removeMessageHandlers(node: BeaconNode) =
|
|||
|
||||
proc setupSelfSlashingProtection(node: BeaconNode, slot: Slot) =
|
||||
# When another client's already running, this is very likely to detect
|
||||
# potential duplicate validators, which can trigger slashing. Assuming
|
||||
# the most pessimal case of two validators started simultaneously, the
|
||||
# probability of triggering a slashable condition is up to 1/n, with n
|
||||
# being the number of epochs one waits before proposing or attesting.
|
||||
# potential duplicate validators, which can trigger slashing.
|
||||
#
|
||||
# Every missed attestation costs approximately 3*get_base_reward(), which
|
||||
# can be up to around 10,000 Wei. Thus, skipping attestations isn't cheap
|
||||
# and one should gauge the likelihood of this simultaneous launch to tune
|
||||
# the epoch delay to one's perceived risk.
|
||||
#
|
||||
# This approach catches both startup and network outage conditions.
|
||||
|
||||
const duplicateValidatorEpochs = 2
|
||||
|
||||
node.processor.gossipSlashingProtection.broadcastStartEpoch =
|
||||
node.processor.doppelgangerProtection.broadcastStartEpoch =
|
||||
slot.epoch + duplicateValidatorEpochs
|
||||
# randomize() already called; also, never probe on first epoch in guard
|
||||
# period, so that existing, running validators can be picked up. Whilst
|
||||
# this reduces entropy for overlapping-start cases, and increases their
|
||||
# collision likelihood, that can be compensated for by increasing guard
|
||||
# epoch periods by 1. As a corollary, 1 guard epoch won't detect when a
|
||||
# duplicate pair overlaps exactly, only the running/starting case. Even
|
||||
# 2 epochs is dangerous because it'll guarantee colliding probes in the
|
||||
# overlapping case.
|
||||
|
||||
let rng = node.network.rng
|
||||
|
||||
# So dPE == 2 -> epoch + 1, always; dPE == 3 -> epoch + (1 or 2), etc.
|
||||
node.processor.gossipSlashingProtection.probeEpoch =
|
||||
slot.epoch + 1 + rng[].rand(duplicateValidatorEpochs.int - 2).uint64
|
||||
doAssert node.processor.gossipSlashingProtection.probeEpoch <
|
||||
node.processor.gossipSlashingProtection.broadcastStartEpoch
|
||||
|
||||
debug "Setting up self-slashing protection",
|
||||
debug "Setting up doppelganger protection",
|
||||
epoch = slot.epoch,
|
||||
probeEpoch = node.processor.gossipSlashingProtection.probeEpoch,
|
||||
broadcastStartEpoch =
|
||||
node.processor.gossipSlashingProtection.broadcastStartEpoch
|
||||
node.processor.doppelgangerProtection.broadcastStartEpoch
|
||||
|
||||
proc updateGossipStatus(node: BeaconNode, slot: Slot) =
|
||||
# Syncing tends to be ~1 block/s, and allow for an epoch of time for libp2p
|
||||
|
|
|
@ -653,9 +653,8 @@ type
|
|||
current_justified_checkpoint*: Checkpoint
|
||||
finalized_checkpoint*: Checkpoint
|
||||
|
||||
DupProtection* = object
|
||||
DoppelgangerProtection* = object
|
||||
broadcastStartEpoch*: Epoch
|
||||
probeEpoch*: Epoch
|
||||
|
||||
func getDepositMessage*(depositData: DepositData): DepositMessage =
|
||||
result.pubkey = depositData.pubkey
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2018-2020 Status Research & Development GmbH
|
||||
# Copyright (c) 2018-2021 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).
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# beacon_chain
|
||||
# Copyright (c) 2018-2020 Status Research & Development GmbH
|
||||
# Copyright (c) 2018-2021 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).
|
||||
|
@ -617,14 +617,16 @@ proc handleValidatorDuties*(node: BeaconNode, lastSlot, slot: Slot) {.async.} =
|
|||
|
||||
# The dontcheck option's a deliberately undocumented escape hatch for the
|
||||
# local testnets and similar development and testing use cases.
|
||||
if curSlot.epoch <
|
||||
node.processor[].gossipSlashingProtection.broadcastStartEpoch and
|
||||
curSlot.epoch != node.processor[].gossipSlashingProtection.probeEpoch and
|
||||
node.config.gossipSlashingProtection == GossipSlashingProtectionMode.stop:
|
||||
#
|
||||
# If broadcastStartEpoch is 0, it hasn't had time to initialize yet, which
|
||||
# means that it'd be okay not to continue, but it won't gossip regardless.
|
||||
if curSlot.epoch <
|
||||
node.processor[].doppelgangerProtection.broadcastStartEpoch and
|
||||
node.config.doppelgangerProtection !=
|
||||
DoppelgangerProtectionMode.dontcheck:
|
||||
notice "Waiting to gossip out to detect potential duplicate validators",
|
||||
broadcastStartEpoch =
|
||||
node.processor[].gossipSlashingProtection.broadcastStartEpoch,
|
||||
probeEpoch = node.processor[].gossipSlashingProtection.probeEpoch
|
||||
node.processor[].doppelgangerProtection.broadcastStartEpoch
|
||||
return
|
||||
|
||||
# Start by checking if there's work we should have done in the past that we
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2020 Status Research & Development GmbH. Licensed under
|
||||
# Copyright (c) 2020-2021 Status Research & Development GmbH. Licensed under
|
||||
# either of:
|
||||
# - Apache License, version 2.0
|
||||
# - MIT license
|
||||
|
@ -385,7 +385,7 @@ for NUM_NODE in $(seq 0 $(( NUM_NODES - 1 ))); do
|
|||
--metrics \
|
||||
--metrics-address="127.0.0.1" \
|
||||
--metrics-port="$(( BASE_METRICS_PORT + NUM_NODE ))" \
|
||||
--gossip-slashing-protection=dontcheck \
|
||||
--doppelganger-protection=dontcheck \
|
||||
${EXTRA_ARGS} \
|
||||
> "${DATA_DIR}/log${NUM_NODE}.txt" 2>&1 &
|
||||
|
||||
|
|
|
@ -105,6 +105,6 @@ $BEACON_NODE_BIN \
|
|||
--metrics \
|
||||
--metrics-address="127.0.0.1" \
|
||||
--metrics-port="$(( $BASE_METRICS_PORT + $NODE_ID ))" \
|
||||
--gossip-slashing-protection=dontcheck \
|
||||
--doppelganger-protection=dontcheck \
|
||||
${ADDITIONAL_BEACON_NODE_ARGS} \
|
||||
"$@"
|
||||
|
|
Loading…
Reference in New Issue