mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-01-09 13:56:23 +00:00
Disconnect peers with low score. (#1747)
* Disconnect peers with low score. * Change PeerScoreLow value. * Add spec url for DisconnectionReason.
This commit is contained in:
parent
7ae689d1dd
commit
1bf8d3af33
@ -662,9 +662,14 @@ proc startSyncManager(node: BeaconNode) =
|
|||||||
proc scoreCheck(peer: Peer): bool =
|
proc scoreCheck(peer: Peer): bool =
|
||||||
if peer.score < PeerScoreLowLimit:
|
if peer.score < PeerScoreLowLimit:
|
||||||
try:
|
try:
|
||||||
debug "Peer score is too low, removing it from PeerPool", peer = peer,
|
debug "Peer score is too low, disconnecting", peer = peer,
|
||||||
peer_score = peer.score, score_low_limit = PeerScoreLowLimit,
|
peer_score = peer.score, score_low_limit = PeerScoreLowLimit,
|
||||||
score_high_limit = PeerScoreHighLimit
|
score_high_limit = PeerScoreHighLimit
|
||||||
|
# We do not care about result of this operation, because even if
|
||||||
|
# disconnect operation fails, peer will still be added to SeenTable
|
||||||
|
# and removed from PeerPool. So it will be not reused for syncing for
|
||||||
|
# `SeenTablePenaltyError` time.
|
||||||
|
asyncSpawn peer.disconnect(PeerScoreLow)
|
||||||
except:
|
except:
|
||||||
discard
|
discard
|
||||||
false
|
false
|
||||||
|
@ -163,11 +163,15 @@ type
|
|||||||
MounterProc* = proc(network: Eth2Node) {.gcsafe.}
|
MounterProc* = proc(network: Eth2Node) {.gcsafe.}
|
||||||
MessageContentPrinter* = proc(msg: pointer): string {.gcsafe.}
|
MessageContentPrinter* = proc(msg: pointer): string {.gcsafe.}
|
||||||
|
|
||||||
|
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.3/specs/phase0/p2p-interface.md#goodbye
|
||||||
DisconnectionReason* = enum
|
DisconnectionReason* = enum
|
||||||
# might see other values on the wire!
|
# might see other values on the wire!
|
||||||
ClientShutDown = 1
|
ClientShutDown = 1
|
||||||
IrrelevantNetwork = 2
|
IrrelevantNetwork = 2
|
||||||
FaultOrError = 3
|
FaultOrError = 3
|
||||||
|
# Clients MAY use reason codes above 128 to indicate alternative,
|
||||||
|
# erroneous request-specific responses.
|
||||||
|
PeerScoreLow = 237 # 79 * 3
|
||||||
|
|
||||||
PeerDisconnected* = object of CatchableError
|
PeerDisconnected* = object of CatchableError
|
||||||
reason*: DisconnectionReason
|
reason*: DisconnectionReason
|
||||||
@ -230,6 +234,8 @@ const
|
|||||||
## Period of time for `ClientShutDown` error reason.
|
## Period of time for `ClientShutDown` error reason.
|
||||||
SeenTableTimeFaultOrError* = 10.minutes
|
SeenTableTimeFaultOrError* = 10.minutes
|
||||||
## Period of time for `FaultOnError` error reason.
|
## Period of time for `FaultOnError` error reason.
|
||||||
|
SeenTablePenaltyError* = 60.minutes
|
||||||
|
## Period of time for peers which score below or equal to zero.
|
||||||
|
|
||||||
template neterr(kindParam: Eth2NetworkingErrorKind): auto =
|
template neterr(kindParam: Eth2NetworkingErrorKind): auto =
|
||||||
err(type(result), Eth2NetworkingError(kind: kindParam))
|
err(type(result), Eth2NetworkingError(kind: kindParam))
|
||||||
@ -303,16 +309,16 @@ proc peerFromStream(network: Eth2Node, conn: Connection): Peer =
|
|||||||
return network.getPeer(conn.peerInfo.peerId)
|
return network.getPeer(conn.peerInfo.peerId)
|
||||||
|
|
||||||
proc getKey*(peer: Peer): PeerID {.inline.} =
|
proc getKey*(peer: Peer): PeerID {.inline.} =
|
||||||
result = peer.info.peerId
|
peer.info.peerId
|
||||||
|
|
||||||
proc getFuture*(peer: Peer): Future[void] {.inline.} =
|
proc getFuture*(peer: Peer): Future[void] {.inline.} =
|
||||||
if peer.disconnectedFut.isNil:
|
if peer.disconnectedFut.isNil:
|
||||||
peer.disconnectedFut = newFuture[void]()
|
peer.disconnectedFut = newFuture[void]()
|
||||||
result = peer.disconnectedFut
|
peer.disconnectedFut
|
||||||
|
|
||||||
proc getScore*(a: Peer): int =
|
proc getScore*(a: Peer): int =
|
||||||
## Returns current score value for peer ``peer``.
|
## Returns current score value for peer ``peer``.
|
||||||
result = a.score
|
a.score
|
||||||
|
|
||||||
proc updateScore*(peer: Peer, score: int) {.inline.} =
|
proc updateScore*(peer: Peer, score: int) {.inline.} =
|
||||||
## Update peer's ``peer`` score with value ``score``.
|
## Update peer's ``peer`` score with value ``score``.
|
||||||
@ -363,13 +369,15 @@ proc isSeen*(network: ETh2Node, peerId: PeerID): bool =
|
|||||||
## yet expired.
|
## yet expired.
|
||||||
let currentTime = now(chronos.Moment)
|
let currentTime = now(chronos.Moment)
|
||||||
if peerId notin network.seenTable:
|
if peerId notin network.seenTable:
|
||||||
return false
|
false
|
||||||
let item = network.seenTable[peerId]
|
else:
|
||||||
if currentTime >= item.stamp:
|
let item = network.seenTable[peerId]
|
||||||
# Peer is in SeenTable, but the time period has expired.
|
if currentTime >= item.stamp:
|
||||||
network.seenTable.del(peerId)
|
# Peer is in SeenTable, but the time period has expired.
|
||||||
return false
|
network.seenTable.del(peerId)
|
||||||
return true
|
false
|
||||||
|
else:
|
||||||
|
true
|
||||||
|
|
||||||
proc addSeen*(network: ETh2Node, peerId: PeerID,
|
proc addSeen*(network: ETh2Node, peerId: PeerID,
|
||||||
period: chronos.Duration) =
|
period: chronos.Duration) =
|
||||||
@ -380,19 +388,26 @@ proc addSeen*(network: ETh2Node, peerId: PeerID,
|
|||||||
proc disconnect*(peer: Peer, reason: DisconnectionReason,
|
proc disconnect*(peer: Peer, reason: DisconnectionReason,
|
||||||
notifyOtherPeer = false) {.async.} =
|
notifyOtherPeer = false) {.async.} =
|
||||||
# TODO: How should we notify the other peer?
|
# TODO: How should we notify the other peer?
|
||||||
if peer.connectionState notin {Disconnecting, Disconnected}:
|
try:
|
||||||
peer.connectionState = Disconnecting
|
if peer.connectionState notin {Disconnecting, Disconnected}:
|
||||||
await peer.network.switch.disconnect(peer.info.peerId)
|
peer.connectionState = Disconnecting
|
||||||
peer.connectionState = Disconnected
|
# We adding peer in SeenTable before actual disconnect to avoid races.
|
||||||
discard peer.network.peerPool.deletePeer(peer)
|
let seenTime = case reason
|
||||||
let seenTime = case reason
|
of ClientShutDown:
|
||||||
of ClientShutDown:
|
SeenTableTimeClientShutDown
|
||||||
SeenTableTimeClientShutDown
|
of IrrelevantNetwork:
|
||||||
of IrrelevantNetwork:
|
SeenTableTimeIrrelevantNetwork
|
||||||
SeenTableTimeIrrelevantNetwork
|
of FaultOrError:
|
||||||
of FaultOrError:
|
SeenTableTimeFaultOrError
|
||||||
SeenTableTimeFaultOrError
|
of PeerScoreLow:
|
||||||
peer.network.addSeen(peer.info.peerId, seenTime)
|
SeenTablePenaltyError
|
||||||
|
peer.network.addSeen(peer.info.peerId, seenTime)
|
||||||
|
await peer.network.switch.disconnect(peer.info.peerId)
|
||||||
|
peer.connectionState = Disconnected
|
||||||
|
except CatchableError as exc:
|
||||||
|
# We do not care about exceptions in disconnection procedure.
|
||||||
|
trace "Exception while disconnecting peer", peer = peer.info.peerId,
|
||||||
|
reason = reason
|
||||||
|
|
||||||
include eth/p2p/p2p_backends_helpers
|
include eth/p2p/p2p_backends_helpers
|
||||||
include eth/p2p/p2p_tracing
|
include eth/p2p/p2p_tracing
|
||||||
|
Loading…
x
Reference in New Issue
Block a user