UNPKG

@savid/rlpx-peeper

Version:

Discover [RLPx](https://github.com/ethereum/devp2p/blob/master/rlpx.md) peers with the [eth/66](https://eips.ethereum.org/EIPS/eip-2481) protocol.

105 lines 3.37 kB
import crypto from 'crypto'; import EventEmitter from 'events'; import { RLPx, DPT } from '@ethereumjs/devp2p'; const ignoredErrors = new RegExp([ 'ECONNRESET', 'EPIPE', 'ETIMEDOUT', 'Hash verification failed', 'Invalid address buffer', 'Invalid timestamp buffer', 'Invalid type', 'Timeout error: ping', 'Peer is banned', 'Invalid MAC', 'Handshake timed out', 'Server already destroyed', ].join('|')); class Server extends EventEmitter { constructor(options) { super(); this.peers = new Map(); this.name = 'rlpx'; this.key = crypto.randomBytes(32); this.bootnodes = options.bootnodes ?? []; this.dnsNetworks = options.dnsNetworks ?? []; this.refreshInterval = options.refreshInterval ?? 30000; this.maxPeers = options.maxPeers ?? 100; this.dnsAddress = options.dnsAddress ?? '8.8.8.8'; } async start() { this.initDpt(); this.initRlpx(); if (!this.dpt) throw new Error('DPT not initialized'); const dnsPeers = (await this.dpt.getDnsPeers()) ?? []; return Promise.all([ ...dnsPeers.map((node) => this.dpt?.bootstrap(node)), ...this.bootnodes.map((bootnode) => this.dpt?.bootstrap({ id: bootnode.id, address: bootnode.ip, udpPort: bootnode.port, tcpPort: bootnode.port, })), ]); } stop() { this.rlpx?.destroy(); this.dpt?.destroy(); } async initDpt() { this.dpt = new DPT(this.key, { refreshInterval: this.refreshInterval, endpoint: { address: '0.0.0.0', udpPort: null, tcpPort: null, }, shouldFindNeighbours: true, shouldGetDnsPeers: true, dnsRefreshQuantity: this.maxPeers, dnsNetworks: this.dnsNetworks, dnsAddr: this.dnsAddress, }); this.dpt.on('error', (error) => { if (error instanceof Error) { if (ignoredErrors.test(error.message)) return; this.emit('error', error); } }); } initRlpx() { this.rlpx = new RLPx(this.key, { dpt: this.dpt, maxPeers: this.maxPeers, capabilities: [ { name: 'eth', version: 66, length: 17, constructor: class ETH66 { _handleMessage() { } }, }, ], common: undefined, }); this.rlpx.on('peer:added', async (rlpxPeer) => { const id = rlpxPeer.getId()?.toString('hex'); const { remoteAddress, remotePort } = rlpxPeer._socket; if (id && remoteAddress && remotePort) { this.emit('peer', `enode://${id}@${remoteAddress}:${remotePort}`); } }); this.rlpx.on('error', (error) => { if (error instanceof Error) { if (ignoredErrors.test(error.message)) return; this.emit('error', error); } }); } } export default Server; //# sourceMappingURL=server.js.map