Skip to content

Commit

Permalink
Devp2p Improvements and Clean-Ups / Client ID Integration (#2538)
Browse files Browse the repository at this point in the history
* devp2p: added singlePeerRun.ts script, new script folder setup structure

* devp2p: removed outdated Parity DPT server ping response hack

* devp2p: improved RLPx HELLO message logging (added protocol version and client ID)

* Client: use client version for RLPx initialization

* Minor
  • Loading branch information
holgerd77 authored Feb 20, 2023
1 parent 4d46313 commit 4aa9753
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 34 deletions.
2 changes: 2 additions & 0 deletions packages/client/lib/net/server/rlpxserver.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DPT as Devp2pDPT, RLPx as Devp2pRLPx } from '@ethereumjs/devp2p'

import { Event } from '../../types'
import { getClientVersion } from '../../util'
import { RlpxPeer } from '../peer/rlpxpeer'

import { Server } from './server'
Expand Down Expand Up @@ -238,6 +239,7 @@ export class RlpxServer extends Server {
private async initRlpx() {
return new Promise<void>((resolve) => {
this.rlpx = new Devp2pRLPx(this.key, {
clientId: Buffer.from(getClientVersion()),
dpt: this.dpt!,
maxPeers: this.config.maxPeers,
capabilities: RlpxPeer.capabilities(Array.from(this.protocols)),
Expand Down
41 changes: 41 additions & 0 deletions packages/devp2p/scripts/singlePeerRun.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { randomBytes } from 'crypto'
import { Chain, Common } from '@ethereumjs/common'
import * as devp2p from '../src/index'

const PEER_ADDRESS = '[ADD_REMOTE_PEER_IP]'
const PEER_PORT = 30303
const ETH_PROTOCOL = devp2p.ETH.eth66

const PRIVATE_KEY = randomBytes(32)

const common = new Common({ chain: Chain.Sepolia })

const dpt = new devp2p.DPT(PRIVATE_KEY, {
refreshInterval: 30000,
endpoint: {
address: '0.0.0.0',
udpPort: null,
tcpPort: null,
},
shouldFindNeighbours: false,
shouldGetDnsPeers: false,
})

const rlpx = new devp2p.RLPx(PRIVATE_KEY, {
dpt,
maxPeers: 1,
capabilities: [ETH_PROTOCOL],
common,
})

const run = async () => {
// Emits 'peer:new' on success, rlpx listens and
// calls into `rlpx.connect
await dpt.addPeer({
address: PEER_ADDRESS,
udpPort: PEER_PORT,
tcpPort: PEER_PORT,
})
}

run()
26 changes: 3 additions & 23 deletions packages/devp2p/src/dpt/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { EventEmitter } from 'events'
import LRUCache = require('lru-cache')
import ms = require('ms')

import { createDeferred, devp2pDebug, formatLogId, keccak256, pk2id } from '../util'
import { createDeferred, devp2pDebug, formatLogId, pk2id } from '../util'

import { decode, encode } from './message'

Expand Down Expand Up @@ -46,7 +46,6 @@ export class Server extends EventEmitter {
_timeout: number
_endpoint: PeerInfo
_requests: Map<string, any>
_parityRequestMap: Map<string, string>
_requestsCache: LRUCache<string, Promise<any>>
_socket: DgramSocket | null
_debug: Debugger
Expand All @@ -60,7 +59,6 @@ export class Server extends EventEmitter {
this._timeout = options.timeout ?? ms('10s')
this._endpoint = options.endpoint ?? { address: '0.0.0.0', udpPort: null, tcpPort: null }
this._requests = new Map()
this._parityRequestMap = new Map()
this._requestsCache = new LRUCache({ max: 1000, maxAge: ms('1s'), stale: false })

const createSocket = options.createSocket ?? dgram.createSocket.bind(null, { type: 'udp4' })
Expand Down Expand Up @@ -149,20 +147,7 @@ export class Server extends EventEmitter {
this.debug(typename, debugMsg)

const msg = encode(typename, data, this._privateKey)
// Parity hack
// There is a bug in Parity up to at lease 1.8.10 not echoing the hash from
// discovery spec (hash: sha3(signature || packet-type || packet-data))
// but just hashing the RLP-encoded packet data (see discovery.rs, on_ping())
// 2018-02-28
if (typename === 'ping') {
const rkeyParity = keccak256(msg.slice(98)).toString('hex')
this._parityRequestMap.set(rkeyParity, msg.slice(0, 32).toString('hex'))
setTimeout(() => {
if (this._parityRequestMap.get(rkeyParity) !== undefined) {
this._parityRequestMap.delete(rkeyParity)
}
}, this._timeout)
}

if (this._socket && typeof peer.udpPort === 'number')
this._socket.send(msg, 0, msg.length, peer.udpPort, peer.address)
return msg.slice(0, 32) // message id
Expand Down Expand Up @@ -201,12 +186,7 @@ export class Server extends EventEmitter {
}

case 'pong': {
let rkey = info.data.hash.toString('hex')
const rkeyParity = this._parityRequestMap.get(rkey)
if (typeof rkeyParity === 'string') {
rkey = rkeyParity
this._parityRequestMap.delete(rkeyParity)
}
const rkey = info.data.hash.toString('hex')
const request = this._requests.get(rkey)
if (request !== undefined) {
this._requests.delete(rkey)
Expand Down
18 changes: 9 additions & 9 deletions packages/devp2p/src/rlpx/peer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,17 +231,17 @@ export class Peer extends EventEmitter {
_sendHello() {
const debugMsg = `Send HELLO to ${this._socket.remoteAddress}:${
this._socket.remotePort
} capabilities=${(this._capabilities ?? [])
} protocolVersion=${BASE_PROTOCOL_VERSION} capabilities=${(this._capabilities ?? [])
// Filter out snap because we can't yet provide snap endpoints to the peers
// TODO: Remove when we can also serve snap requests from other peers
.filter((c) => c.name !== 'snap')
.map((c) => `${c.name}${c.version}`)
.join(',')}`
.join(',')} clientId=${this._clientId}`
this.debug('HELLO', debugMsg)
const payload: HelloMsg = [
int2buffer(BASE_PROTOCOL_VERSION),
this._clientId,
this._capabilities!.map((obj: any) => [Buffer.from(obj.name), int2buffer(obj.version)]),
this._capabilities!.map((c) => [Buffer.from(c.name), int2buffer(c.version)]),
this._port === null ? Buffer.allocUnsafe(0) : int2buffer(this._port),
this._id,
]
Expand Down Expand Up @@ -379,9 +379,9 @@ export class Peer extends EventEmitter {

const debugMsg = `Received HELLO ${this._socket.remoteAddress}:${
this._socket.remotePort
} capabilities=${(this._hello.capabilities ?? [])
} protocolVersion=${this._hello.protocolVersion} capabilities=${(this._hello.capabilities ?? [])
.map((c) => `${c.name}${c.version}`)
.join(',')}`
.join(',')} clientId=${this._hello.clientId}`
this.debug('HELLO', debugMsg)

if (this._remoteId === null) {
Expand All @@ -400,10 +400,10 @@ export class Peer extends EventEmitter {

const shared: any = {}
for (const item of this._hello.capabilities) {
for (const obj of this._capabilities!) {
if (obj.name !== item.name || obj.version !== item.version) continue
if (shared[obj.name] !== undefined && shared[obj.name].version > obj.version) continue
shared[obj.name] = obj
for (const c of this._capabilities!) {
if (c.name !== item.name || c.version !== item.version) continue
if (shared[c.name] !== undefined && shared[c.name].version > c.version) continue
shared[c.name] = c
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/devp2p/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"extends": "../../config/tsconfig.json",
"include": ["src/**/*.ts", "test/**/*.ts", "examples/**/*.ts"],
"include": ["src/**/*.ts", "test/**/*.ts", "examples/**/*.ts", "scripts/**/*.ts"],
"compilerOptions": {
"baseUrl": ".",
"typeRoots": ["node_modules/@types", "src/@types"]
Expand Down
2 changes: 1 addition & 1 deletion packages/devp2p/tsconfig.prod.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"extends": "../../config/tsconfig.prod.json",
"exclude": ["test", "examples", "node_modules", "dist"],
"exclude": ["test", "examples", "scripts", "node_modules", "dist"],
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist",
Expand Down

0 comments on commit 4aa9753

Please sign in to comment.