diff --git a/lib/p2p/NodeList.ts b/lib/p2p/NodeList.ts index 0cf494ef6..2cf119669 100644 --- a/lib/p2p/NodeList.ts +++ b/lib/p2p/NodeList.ts @@ -12,6 +12,9 @@ const reputationEventWeight = { [ReputationEvent.PacketTimeout]: -1, [ReputationEvent.SwapFailure]: -10, [ReputationEvent.SwapSuccess]: 1, + [ReputationEvent.InvalidMessage]: -10, + [ReputationEvent.UnknownPacketType]: -20, + [ReputationEvent.UnparseableMessage]: -10, }; // TODO: inform node about getting banned diff --git a/lib/p2p/Peer.ts b/lib/p2p/Peer.ts index 8bf3c0008..8be9ef19d 100644 --- a/lib/p2p/Peer.ts +++ b/lib/p2p/Peer.ts @@ -1,6 +1,7 @@ import assert from 'assert'; import net, { Socket } from 'net'; import { EventEmitter } from 'events'; +import { ReputationEvent } from '../types/enums'; import Parser, { ParserError, ParserErrorType } from './Parser'; import * as packets from './packets/types'; import Logger from '../Logger'; @@ -29,9 +30,9 @@ interface Peer { on(event: 'handshake', listener: () => void): this; once(event: 'open', listener: () => void): this; once(event: 'close', listener: () => void): this; - once(event: 'ban', listener: () => void): this; + once(event: 'reputation', listener: (event: ReputationEvent) => void): this; emit(event: 'connect'): boolean; - emit(event: 'ban'): boolean; + emit(event: 'reputation', reputationEvent: ReputationEvent): boolean; emit(event: 'open'): boolean; emit(event: 'close'): boolean; emit(event: 'error', err: Error): boolean; @@ -53,7 +54,6 @@ class Peer extends EventEmitter { private pingTimer?: NodeJS.Timer; private responseMap: Map = new Map(); private connectTime!: number; - private banScore = 0; private lastRecv = 0; private lastSend = 0; private handshakeState?: HandshakeState; @@ -256,18 +256,6 @@ class Peer extends EventEmitter { } } - private increaseBan = (score: number): boolean => { - this.banScore += score; - - if (this.banScore >= 100) { // TODO: make configurable - this.logger.debug(`Ban threshold exceeded (${this.nodePubKey})`); - this.emit('ban'); - return true; - } - - return false; - } - /** * Ensure we are connected (for inbound connections) or listen for the `connect` socket event (for outbound connections) * and set the [[connectTime]] timestamp. If an outbound connection attempt errors or times out, throw an error. @@ -487,15 +475,15 @@ class Peer extends EventEmitter { switch (err.type) { case ParserErrorType.UnparseableMessage: this.logger.warn(`Unparsable peer message: ${err.payload}`); - this.increaseBan(10); + this.emit('reputation', ReputationEvent.UnparseableMessage); break; case ParserErrorType.InvalidMessage: this.logger.warn(`Invalid peer message: ${err.payload}`); - this.increaseBan(10); + this.emit('reputation', ReputationEvent.InvalidMessage); break; case ParserErrorType.UnknownPacketType: this.logger.warn(`Unknown peer message type: ${err.payload}`); - this.increaseBan(20); + this.emit('reputation', ReputationEvent.UnknownPacketType); } }); } diff --git a/lib/p2p/Pool.ts b/lib/p2p/Pool.ts index f80a83e21..ffb102da8 100644 --- a/lib/p2p/Pool.ts +++ b/lib/p2p/Pool.ts @@ -647,13 +647,10 @@ class Pool extends EventEmitter { this.emit('peer.close', peer); }); - peer.once('ban', async () => { - this.logger.debug(`Banning peer (${peer.nodePubKey})`); + peer.once('reputation', async (event) => { + this.logger.debug(`Peer (${peer.nodePubKey}), received reputation event: ${ReputationEvent[event]}`); if (peer.nodePubKey) { - await this.nodes.ban(peer.nodePubKey); - } - if (peer.connected) { - peer.close(); + await this.nodes.addReputationEvent(peer.nodePubKey, event); } }); } diff --git a/lib/types/enums.ts b/lib/types/enums.ts index a8890a2ad..c29c0af58 100644 --- a/lib/types/enums.ts +++ b/lib/types/enums.ts @@ -47,6 +47,9 @@ export enum ReputationEvent { PacketTimeout = 2, SwapFailure = 3, SwapSuccess = 4, + UnparseableMessage = 5, + InvalidMessage = 6, + UnknownPacketType = 7, } export enum SwapFailureReason {