UNPKG

@lodestar/beacon-node

Version:

A Typescript implementation of the beacon chain

92 lines 3.32 kB
import EventEmitter from "node:events"; import { ENR, SignableENR } from "@chainsafe/enr"; import { Thread, Worker, spawn } from "@chainsafe/threads"; import { privateKeyToProtobuf } from "@libp2p/crypto/keys"; import { chainConfigFromJson, chainConfigToJson } from "@lodestar/config"; /** * Wrapper class abstracting the details of discv5 worker instantiation and message-passing */ export class Discv5Worker extends EventEmitter { constructor(opts, workerApi) { super(); this.opts = opts; this.workerApi = workerApi; this.closed = false; this.subscription = workerApi.discovered().subscribe((enrObj) => this.onDiscovered(enrObj)); } static async init(opts) { const workerData = { enr: opts.discv5.enr, privateKeyProto: privateKeyToProtobuf(opts.privateKey), bindAddrs: opts.discv5.bindAddrs, config: opts.discv5.config ?? {}, bootEnrs: opts.discv5.bootEnrs, metrics: Boolean(opts.metrics), chainConfig: chainConfigFromJson(chainConfigToJson(opts.config)), genesisValidatorsRoot: opts.config.genesisValidatorsRoot, loggerOpts: opts.logger.toOpts(), genesisTime: opts.genesisTime, }; const worker = new Worker("./worker.js", { workerData }); const workerApi = await spawn(worker, { // A Lodestar Node may do very expensive task at start blocking the event loop and causing // the initialization to timeout. The number below is big enough to almost disable the timeout timeout: 5 * 60 * 1000, }); return new Discv5Worker(opts, workerApi); } async close() { if (this.closed) return; this.closed = true; this.subscription.unsubscribe(); await this.workerApi.close(); await Thread.terminate(this.workerApi); } onDiscovered(obj) { const enr = this.decodeEnr(obj); if (enr) { this.emit("discovered", enr); } } async enr() { const obj = await this.workerApi.enr(); return new SignableENR(obj.kvs, obj.seq, this.opts.privateKey.raw); } setEnrValue(key, value) { return this.workerApi.setEnrValue(key, value); } async kadValues() { return this.decodeEnrs(await this.workerApi.kadValues()); } discoverKadValues() { return this.workerApi.discoverKadValues(); } async findRandomNode() { return this.decodeEnrs(await this.workerApi.findRandomNode()); } scrapeMetrics() { return this.workerApi.scrapeMetrics(); } async writeProfile(durationMs, dirpath) { return this.workerApi.writeProfile(durationMs, dirpath); } async writeHeapSnapshot(prefix, dirpath) { return this.workerApi.writeHeapSnapshot(prefix, dirpath); } decodeEnrs(objs) { const enrs = []; for (const obj of objs) { const enr = this.decodeEnr(obj); if (enr) { enrs.push(enr); } } return enrs; } decodeEnr(obj) { this.opts.metrics?.discv5.decodeEnrAttemptCount.inc(1); return new ENR(obj.kvs, obj.seq, obj.signature); } } //# sourceMappingURL=index.js.map