Skip to content

Commit 838d6c4

Browse files
committed
devp2p -> connection reliability: subdivided interval calls to refill RLPx peer connections to improve networking distribution and connection reliability
1 parent 75d224b commit 838d6c4

File tree

2 files changed

+26
-8
lines changed

2 files changed

+26
-8
lines changed

packages/devp2p/src/dpt/dpt.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,9 @@ export class DPT extends EventEmitter {
173173
this._refreshIntervalSelectionCounter = (this._refreshIntervalSelectionCounter + 1) % 10
174174

175175
const peers = this.getPeers()
176-
debug(`call .refresh (${peers.length} peers in table)`)
176+
debug(
177+
`call .refresh() (selector ${this._refreshIntervalSelectionCounter}) (${peers.length} peers in table)`
178+
)
177179

178180
for (const peer of peers) {
179181
// Randomly distributed selector based on peer ID

packages/devp2p/src/rlpx/rlpx.ts

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import LRUCache from 'lru-cache'
88
import Common from '@ethereumjs/common'
99
// note: relative path only valid in .js file in dist
1010
const { version: pVersion } = require('../../package.json')
11-
import { pk2id, createDeferred, formatLogId } from '../util'
11+
import { pk2id, createDeferred, formatLogId, buffer2int } from '../util'
1212
import { Peer, DISCONNECT_REASONS, Capabilities } from './peer'
1313
import { DPT, PeerInfo } from '../dpt'
1414

@@ -31,6 +31,7 @@ export interface RLPxOptions {
3131
export class RLPx extends EventEmitter {
3232
_privateKey: Buffer
3333
_id: Buffer
34+
3435
_timeout: number
3536
_maxPeers: number
3637
_clientId: Buffer
@@ -39,11 +40,14 @@ export class RLPx extends EventEmitter {
3940
_common: Common
4041
_listenPort: number | null
4142
_dpt: DPT | null
43+
4244
_peersLRU: LRUCache<string, boolean>
4345
_peersQueue: { peer: PeerInfo; ts: number }[]
4446
_server: net.Server | null
4547
_peers: Map<string, net.Socket | Peer>
48+
4649
_refillIntervalId: NodeJS.Timeout
50+
_refillIntervalSelectionCounter: number = 0
4751

4852
constructor(privateKey: Buffer, options: RLPxOptions) {
4953
super()
@@ -98,7 +102,9 @@ export class RLPx extends EventEmitter {
98102
this._peers = new Map()
99103
this._peersQueue = []
100104
this._peersLRU = new LRUCache({ max: 25000 })
101-
this._refillIntervalId = setInterval(() => this._refillConnections(), ms('10s'))
105+
const REFILL_INTERVALL = ms('10s')
106+
const refillIntervalSubdivided = Math.floor(REFILL_INTERVALL / 10)
107+
this._refillIntervalId = setInterval(() => this._refillConnections(), refillIntervalSubdivided)
102108
}
103109

104110
listen(...args: any[]) {
@@ -261,17 +267,27 @@ export class RLPx extends EventEmitter {
261267
_refillConnections() {
262268
if (!this._isAlive()) return
263269
debug(
264-
`refill connections.. peers: ${this._peers.size}, queue size: ${
265-
this._peersQueue.length
266-
}, open slots: ${this._getOpenSlots()}`
270+
`refill connections.. (selector ${this._refillIntervalSelectionCounter}) peers: ${
271+
this._peers.size
272+
}, queue size: ${this._peersQueue.length}, open slots: ${this._getOpenSlots()}`
267273
)
274+
// Rotating selection counter going in loop from 0..9
275+
this._refillIntervalSelectionCounter = (this._refillIntervalSelectionCounter + 1) % 10
268276

269277
this._peersQueue = this._peersQueue.filter((item) => {
270278
if (this._getOpenSlots() === 0) return true
271279
if (item.ts > Date.now()) return true
272280

273-
this._connectToPeer(item.peer)
274-
return false
281+
// Randomly distributed selector based on peer ID
282+
// to decide on subdivided execution
283+
const selector = buffer2int((item.peer.id! as Buffer).slice(0, 1)) % 10
284+
if (selector === this._refillIntervalSelectionCounter) {
285+
this._connectToPeer(item.peer)
286+
return false
287+
} else {
288+
// Still keep peer in queue
289+
return true
290+
}
275291
})
276292
}
277293
}

0 commit comments

Comments
 (0)