Skip to content

Commit 86fb51d

Browse files
authored
Merge pull request #1029 from ethereumjs/devp2p-dpt-type-improvements
Devp2p DPT Type Improvements
2 parents 9937927 + 9cc2ec7 commit 86fb51d

File tree

9 files changed

+114
-64
lines changed

9 files changed

+114
-64
lines changed

packages/client/lib/net/server/rlpxserver.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,17 +122,17 @@ export class RlpxServer extends Server {
122122
async bootstrap(): Promise<void> {
123123
const promises = this.bootnodes.map((node) => {
124124
const bootnode = {
125-
address: node.ip,
125+
address: node.ip!,
126126
udpPort: node.port,
127127
tcpPort: node.port,
128128
}
129-
try {
130-
return this.dpt!.bootstrap(bootnode)
131-
} catch (e) {
132-
this.error(e)
133-
}
129+
return this.dpt!.bootstrap(bootnode)
134130
})
135-
await Promise.all(promises)
131+
try {
132+
await Promise.all(promises)
133+
} catch (e) {
134+
this.error(e)
135+
}
136136
}
137137

138138
/**

packages/client/lib/service/ethereumservice.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ export interface EthereumServiceOptions extends ServiceOptions {
1111
/* Blockchain database */
1212
db?: LevelUp
1313

14-
/* Protocol timeout in ms (default: 8000) */
15-
timeout?: number
16-
17-
/* Sync retry interval in ms (default: 1000) */
14+
/* Sync retry interval in ms (default: 8000) */
1815
interval?: number
16+
17+
/* Protocol timeout in ms (default: 2000) */
18+
timeout?: number
1919
}
2020

2121
/**
@@ -39,7 +39,7 @@ export class EthereumService extends Service {
3939
this.flow = new FlowControl()
4040
this.chain = options.chain ?? new Chain(options)
4141
this.interval = options.interval ?? 8000
42-
this.timeout = options.timeout ?? 1000
42+
this.timeout = options.timeout ?? 2000
4343
}
4444

4545
/**

packages/client/test/net/server/rlpxserver.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ tape('[RlpxServer]', async (t) => {
7575
server.dpt = td.object()
7676
server.rlpx = td.object()
7777
td.when(
78-
server.dpt!.bootstrap({ address: '10.0.0.1', udpPort: '1234', tcpPort: '1234' })
78+
server.dpt!.bootstrap({ address: '10.0.0.1', udpPort: 1234, tcpPort: 1234 })
7979
).thenResolve()
8080
td.when(
81-
server.dpt!.bootstrap({ address: '10.0.0.2', udpPort: '1234', tcpPort: '1234' })
81+
(server.dpt! as any).bootstrap({ address: '10.0.0.2', udpPort: '1234', tcpPort: '1234' })
8282
).thenReject(new Error('err0'))
8383
server.on('error', (err: Error) => t.equals(err.message, 'err0', 'got error'))
8484
await server.start()
@@ -109,10 +109,10 @@ tape('[RlpxServer]', async (t) => {
109109
destroy: td.func(),
110110
})
111111
td.when(
112-
server.dpt?.bootstrap({ address: '10.0.0.1', udpPort: '1234', tcpPort: '1234' })
112+
server.dpt!.bootstrap({ address: '10.0.0.1', udpPort: 1234, tcpPort: 1234 })
113113
).thenResolve(undefined)
114114
td.when(
115-
server.dpt?.bootstrap({ address: '10.0.0.2', udpPort: '1234', tcpPort: '1234' })
115+
(server.dpt! as any).bootstrap({ address: '10.0.0.2', udpPort: '1234', tcpPort: '1234' })
116116
).thenReject(new Error('err0'))
117117
server.on('error', (err) => t.equals(err.message, 'err0', 'got error'))
118118
await server.start()

packages/devp2p/src/dpt/ban-list.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,25 @@ import LRUCache from 'lru-cache'
22
import { debug as createDebugLogger } from 'debug'
33
import { KBucket } from './kbucket'
44
import { formatLogId } from '../util'
5+
import { PeerInfo } from './dpt'
56

67
const debug = createDebugLogger('devp2p:dpt:ban-list')
78
const verbose = createDebugLogger('verbose').enabled
89

910
export class BanList {
10-
private lru: LRUCache<any, boolean>
11+
private lru: LRUCache<string, boolean>
1112
constructor() {
1213
this.lru = new LRUCache({ max: 30000 }) // 10k should be enough (each peer obj can has 3 keys)
1314
}
1415

15-
add(obj: any, maxAge?: number) {
16+
add(obj: string | Buffer | PeerInfo, maxAge?: number) {
1617
for (const key of KBucket.getKeys(obj)) {
1718
this.lru.set(key, true, maxAge)
1819
debug(`Added peer ${formatLogId(key, verbose)}, size: ${this.lru.length}`)
1920
}
2021
}
2122

22-
has(obj: any): boolean {
23+
has(obj: string | Buffer | PeerInfo): boolean {
2324
return KBucket.getKeys(obj).some((key: string) => Boolean(this.lru.get(key)))
2425
}
2526
}

packages/devp2p/src/dpt/dpt.ts

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,43 @@ import { Server as DPTServer } from './server'
1010

1111
const debug = createDebugLogger('devp2p:dpt')
1212

13+
export interface PeerInfo {
14+
id?: Uint8Array | Buffer
15+
address?: string
16+
udpPort?: number | null
17+
tcpPort?: number | null
18+
}
19+
20+
export interface DPTOptions {
21+
/**
22+
* Timeout for peer requests
23+
*
24+
* Default: 10s
25+
*/
26+
timeout?: number
27+
28+
/**
29+
* Network info to send a long a request
30+
*
31+
* Default: 0.0.0.0, no UDP or TCP port provided
32+
*/
33+
endpoint?: PeerInfo
34+
35+
/**
36+
* Function for socket creation
37+
*
38+
* Default: dgram-created socket
39+
*/
40+
createSocket?: Function
41+
42+
/**
43+
* Interval for peer table refresh
44+
*
45+
* Default: 60s
46+
*/
47+
refreshInterval?: number
48+
}
49+
1350
export class DPT extends EventEmitter {
1451
privateKey: Buffer
1552
banlist: BanList
@@ -19,7 +56,7 @@ export class DPT extends EventEmitter {
1956
private _server: DPTServer
2057
private _refreshIntervalId: NodeJS.Timeout
2158

22-
constructor(privateKey: Buffer, options: any) {
59+
constructor(privateKey: Buffer, options: DPTOptions) {
2360
super()
2461

2562
this.privateKey = Buffer.from(privateKey)
@@ -28,14 +65,14 @@ export class DPT extends EventEmitter {
2865
this.banlist = new BanList()
2966

3067
this._kbucket = new KBucket(this._id)
31-
this._kbucket.on('added', (peer) => this.emit('peer:added', peer))
32-
this._kbucket.on('removed', (peer) => this.emit('peer:removed', peer))
68+
this._kbucket.on('added', (peer: PeerInfo) => this.emit('peer:added', peer))
69+
this._kbucket.on('removed', (peer: PeerInfo) => this.emit('peer:removed', peer))
3370
this._kbucket.on('ping', this._onKBucketPing)
3471

3572
this._server = new DPTServer(this, this.privateKey, {
36-
createSocket: options.createSocket,
3773
timeout: options.timeout,
3874
endpoint: options.endpoint,
75+
createSocket: options.createSocket,
3976
})
4077
this._server.once('listening', () => this.emit('listening'))
4178
this._server.once('close', () => this.emit('close'))
@@ -55,7 +92,7 @@ export class DPT extends EventEmitter {
5592
this._server.destroy(...args)
5693
}
5794

58-
_onKBucketPing(oldPeers: any[], newPeer: any): void {
95+
_onKBucketPing(oldPeers: PeerInfo[], newPeer: PeerInfo): void {
5996
if (this.banlist.has(newPeer)) return
6097

6198
let count = 0
@@ -81,15 +118,15 @@ export class DPT extends EventEmitter {
81118
for (const peer of peers) this.addPeer(peer).catch(() => {})
82119
}
83120

84-
async bootstrap(peer: any): Promise<void> {
121+
async bootstrap(peer: PeerInfo): Promise<void> {
85122
debug(`bootstrap with peer ${peer.address}:${peer.udpPort}`)
86123

87124
peer = await this.addPeer(peer)
88125
if (!this._id) return
89126
this._server.findneighbours(peer, this._id)
90127
}
91128

92-
async addPeer(obj: any): Promise<any> {
129+
async addPeer(obj: PeerInfo): Promise<any> {
93130
if (this.banlist.has(obj)) throw new Error('Peer is banned')
94131
debug(`attempt adding peer ${obj.address}:${obj.udpPort}`)
95132

@@ -109,23 +146,23 @@ export class DPT extends EventEmitter {
109146
}
110147
}
111148

112-
getPeer(obj: any): any {
149+
getPeer(obj: string | Buffer | PeerInfo) {
113150
return this._kbucket.get(obj)
114151
}
115152

116-
getPeers(): any[] {
153+
getPeers() {
117154
return this._kbucket.getAll()
118155
}
119156

120-
getClosestPeers(id: string): any {
157+
getClosestPeers(id: string) {
121158
return this._kbucket.closest(id)
122159
}
123160

124161
removePeer(obj: any) {
125162
this._kbucket.remove(obj)
126163
}
127164

128-
banPeer(obj: any, maxAge?: number) {
165+
banPeer(obj: string | Buffer | PeerInfo, maxAge?: number) {
129166
this.banlist.add(obj, maxAge)
130167
this._kbucket.remove(obj)
131168
}

packages/devp2p/src/dpt/kbucket.ts

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,58 @@
11
import { EventEmitter } from 'events'
22
import _KBucket = require('k-bucket')
3+
import { PeerInfo } from './dpt'
34

45
const KBUCKET_SIZE = 16
56
const KBUCKET_CONCURRENCY = 3
67

7-
export interface KObj {
8-
id?: string
9-
port?: string
10-
address?: string
8+
export interface CustomContact extends PeerInfo {
9+
id: Uint8Array | Buffer
10+
vectorClock: number
1111
}
1212

1313
export class KBucket extends EventEmitter {
14-
_peers: Map<string, any> = new Map()
14+
_peers: Map<string, PeerInfo> = new Map()
1515
_kbucket: _KBucket
16-
constructor(id: string | Buffer) {
16+
constructor(localNodeId: Buffer) {
1717
super()
1818

19-
this._kbucket = new _KBucket({
20-
localNodeId: typeof id === 'string' ? Buffer.from(id) : id,
19+
this._kbucket = new _KBucket<CustomContact>({
20+
localNodeId,
2121
numberOfNodesPerKBucket: KBUCKET_SIZE,
2222
numberOfNodesToPing: KBUCKET_CONCURRENCY,
2323
})
2424

25-
this._kbucket.on('added', (peer: any) => {
25+
this._kbucket.on('added', (peer: PeerInfo) => {
2626
KBucket.getKeys(peer).forEach((key) => this._peers.set(key, peer))
2727
this.emit('added', peer)
2828
})
2929

30-
this._kbucket.on('removed', (peer: any) => {
30+
this._kbucket.on('removed', (peer: PeerInfo) => {
3131
KBucket.getKeys(peer).forEach((key) => this._peers.delete(key))
3232
this.emit('removed', peer)
3333
})
3434

35-
this._kbucket.on('ping', (...args: any[]) => this.emit('ping', ...args))
35+
this._kbucket.on('ping', (oldPeers: PeerInfo[], newPeer: PeerInfo) => {
36+
this.emit('ping', { oldPeers, newPeer })
37+
})
3638
}
3739

38-
static getKeys(obj: Buffer | string | KObj): string[] {
40+
static getKeys(obj: Buffer | string | PeerInfo): string[] {
3941
if (Buffer.isBuffer(obj)) return [obj.toString('hex')]
4042
if (typeof obj === 'string') return [obj]
4143

4244
const keys = []
4345
if (Buffer.isBuffer(obj.id)) keys.push(obj.id.toString('hex'))
44-
if (obj.address && obj.port) keys.push(`${obj.address}:${obj.port}`)
46+
//if (obj.address && obj.port) keys.push(`${obj.address}:${obj.port}`)
4547
return keys
4648
}
4749

48-
add(peer: any) {
50+
add(peer: PeerInfo) {
4951
const isExists = KBucket.getKeys(peer).some((key) => this._peers.has(key))
50-
if (!isExists) this._kbucket.add(peer)
52+
if (!isExists) this._kbucket.add(peer as CustomContact)
5153
}
5254

53-
get(obj: Buffer | string | KObj) {
55+
get(obj: Buffer | string | PeerInfo) {
5456
for (const key of KBucket.getKeys(obj)) {
5557
const peer = this._peers.get(key)
5658
if (peer !== undefined) return peer
@@ -59,16 +61,16 @@ export class KBucket extends EventEmitter {
5961
return null
6062
}
6163

62-
getAll(): Array<any> {
64+
getAll(): Array<PeerInfo> {
6365
return this._kbucket.toArray()
6466
}
6567

66-
closest(id: string): any {
68+
closest(id: string): PeerInfo[] {
6769
return this._kbucket.closest(Buffer.from(id), KBUCKET_SIZE)
6870
}
6971

70-
remove(obj: Buffer | string | KObj) {
72+
remove(obj: Buffer | string | PeerInfo) {
7173
const peer = this.get(obj)
72-
if (peer !== null) this._kbucket.remove(peer.id)
74+
if (peer !== null) this._kbucket.remove((peer as CustomContact).id)
7375
}
7476
}

packages/devp2p/src/dpt/message.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,14 @@ import ip from 'ip'
33
import * as rlp from 'rlp'
44
import secp256k1 from 'secp256k1'
55
import { keccak256, int2buffer, buffer2int, assertEq, unstrictDecode } from '../util'
6+
import { PeerInfo } from './dpt'
67

78
const debug = createDebugLogger('devp2p:dpt:server')
89

910
function getTimestamp() {
1011
return (Date.now() / 1000) | 0
1112
}
1213

13-
export interface PeerInfo {
14-
id?: Buffer
15-
address?: string
16-
udpPort?: number | null
17-
tcpPort?: number | null
18-
}
19-
2014
const timestamp = {
2115
encode: function (value = getTimestamp() + 60) {
2216
const buffer = Buffer.allocUnsafe(4)
@@ -133,7 +127,7 @@ type OutNeighborMsg = { [0]: Buffer[][]; [1]: Buffer }
133127
const neighbours = {
134128
encode: function (obj: InNeighborMsg): OutNeighborMsg {
135129
return [
136-
obj.peers.map((peer: PeerInfo) => endpoint.encode(peer).concat(peer.id!)),
130+
obj.peers.map((peer: PeerInfo) => endpoint.encode(peer).concat(peer.id! as Buffer)),
137131
timestamp.encode(obj.timestamp),
138132
]
139133
},

0 commit comments

Comments
 (0)