From a58631df380c183af963e076208a89d6dafc6135 Mon Sep 17 00:00:00 2001 From: mitsujutsu Date: Wed, 19 Jun 2019 16:00:55 +0200 Subject: [PATCH] Add integration test for inbound peer eviction protection --- elements/lisk-p2p/src/peer/base.ts | 9 ++- elements/lisk-p2p/test/integration/p2p.ts | 82 ++++++++++++++++++++++- 2 files changed, 87 insertions(+), 4 deletions(-) diff --git a/elements/lisk-p2p/src/peer/base.ts b/elements/lisk-p2p/src/peer/base.ts index e531b62d575..0cfcfc7dc19 100644 --- a/elements/lisk-p2p/src/peer/base.ts +++ b/elements/lisk-p2p/src/peer/base.ts @@ -88,7 +88,7 @@ export const DEFAULT_CONNECT_TIMEOUT = 2000; export const DEFAULT_ACK_TIMEOUT = 2000; export const DEFAULT_REPUTATION_SCORE = 100; export const DEFAULT_RATE_INTERVAL = 1000; -export const DEFAULT_PRODUCTIVITY_RESET_INTERVAL = 3600000; +export const DEFAULT_PRODUCTIVITY_RESET_INTERVAL = 2000; export const DEFAULT_PRODUCTIVITY = { requestCounter: 0, responseCounter: 0, @@ -183,8 +183,11 @@ export class Peer extends EventEmitter { this._callCounter = new Map(); }, DEFAULT_RATE_INTERVAL); this._productivityResetInterval = setInterval(() => { - // If peer has not responded within an hour, reset productivity to 0 - if(this.productivity.lastResponded < (Date.now() - DEFAULT_PRODUCTIVITY_RESET_INTERVAL)) { + // If peer has not recently responded, reset productivity to 0 + if ( + this.productivity.lastResponded < + Date.now() - DEFAULT_PRODUCTIVITY_RESET_INTERVAL + ) { this.productivity = DEFAULT_PRODUCTIVITY; } }, DEFAULT_PRODUCTIVITY_RESET_INTERVAL); diff --git a/elements/lisk-p2p/test/integration/p2p.ts b/elements/lisk-p2p/test/integration/p2p.ts index af89b85556f..a7bba4783b7 100644 --- a/elements/lisk-p2p/test/integration/p2p.ts +++ b/elements/lisk-p2p/test/integration/p2p.ts @@ -24,8 +24,8 @@ import { P2PPeerSelectionForSendInput, P2PPeerSelectionForRequestInput, P2PPeerSelectionForConnectionInput, - P2PNodeInfo, } from '../../src/p2p_types'; +import { InboundPeer } from '../../src/peer'; describe('Integration tests for P2P library', () => { before(() => { @@ -1485,4 +1485,84 @@ describe('Integration tests for P2P library', () => { }); }); }); + + describe('Network with peer inbound eviction protection enabled', () => { + const NETWORK_PEER_COUNT_WITH_LIMIT = 10; + const MAX_INBOUND_CONNECTIONS = 5; + const DISCOVERY_INTERVAL_WITH_LIMIT = 5; + const POPULATOR_INTERVAL_WITH_LIMIT = 10; + beforeEach(async () => { + p2pNodeList = [...new Array(NETWORK_PEER_COUNT_WITH_LIMIT).keys()].map( + index => { + // Each node will have the previous node in the sequence as a seed peer except the first node. + const seedPeers = [ + { + ipAddress: '127.0.0.1', + wsPort: + NETWORK_START_PORT + + ((index + 1) % NETWORK_PEER_COUNT_WITH_LIMIT), + }, + ]; + + const nodePort = NETWORK_START_PORT + index; + return new P2P({ + connectTimeout: 5000, + ackTimeout: 5000, + seedPeers, + wsEngine: 'ws', + discoveryInterval: DISCOVERY_INTERVAL_WITH_LIMIT, + populatorInterval: POPULATOR_INTERVAL_WITH_LIMIT, + maxOutboundConnections: MAX_INBOUND_CONNECTIONS, + maxInboundConnections: 5, + evictionProtectionEnabled: true, + nodeInfo: { + wsPort: nodePort, + nethash: + 'da3ed6a45429278bac2666961289ca17ad86595d33b31037615d4b8e8f158bba', + version: '1.0.1', + protocolVersion: '1.0.1', + minVersion: '1.0.0', + os: platform(), + height: 0, + broadhash: + '2768b267ae621a9ed3b3034e2e8a1bed40895c621bbb1bbd613d92b9d24e54b5', + nonce: `O2wTkjqplHII${nodePort}`, + }, + }); + }, + ); + + // Start nodes incrementally to make inbound eviction behavior predictable + p2pNodeList.forEach(async p2p => { + await wait(600); + p2p.start(); + }); + await wait(1000); + }); + + afterEach(async () => { + await Promise.all( + p2pNodeList + .filter(p2p => p2p.isActive) + .map(async p2p => await p2p.stop()), + ); + await wait(100); + }); + + describe('Inbound peer evictions', () => { + it('should evict inbound peer which connected the latest', async () => { + p2pNodeList.forEach(async (p2p, i) => { + // Disregard early peers who may be re-discovered by already evicted peers + if (i <= 3) { + return; + } + const inboundPeers = p2p['_peerPool'] + .getPeers(InboundPeer) + .map(peer => peer.wsPort); + const lastPeerPort = 5009; + expect(inboundPeers).to.not.include(lastPeerPort); + }); + }); + }); + }); });