UNPKG

@waku/enr

Version:
146 lines 4.92 kB
import { Logger } from "@waku/utils"; import { ERR_INVALID_ID } from "./constants.js"; import { keccak256, verifySignature } from "./crypto.js"; import { locationMultiaddrFromEnrFields } from "./get_multiaddr.js"; import { createPeerIdFromPublicKey } from "./peer_id.js"; import { RawEnr } from "./raw_enr.js"; import * as v4 from "./v4.js"; const log = new Logger("enr"); export var TransportProtocol; (function (TransportProtocol) { TransportProtocol["TCP"] = "tcp"; TransportProtocol["UDP"] = "udp"; })(TransportProtocol || (TransportProtocol = {})); export var TransportProtocolPerIpVersion; (function (TransportProtocolPerIpVersion) { TransportProtocolPerIpVersion["TCP4"] = "tcp4"; TransportProtocolPerIpVersion["UDP4"] = "udp4"; TransportProtocolPerIpVersion["TCP6"] = "tcp6"; TransportProtocolPerIpVersion["UDP6"] = "udp6"; })(TransportProtocolPerIpVersion || (TransportProtocolPerIpVersion = {})); export class ENR extends RawEnr { static RECORD_PREFIX = "enr:"; peerId; static create(kvs = {}, seq = BigInt(1), signature) { const enr = new ENR(kvs, seq, signature); try { const publicKey = enr.publicKey; if (publicKey) { enr.peerId = createPeerIdFromPublicKey(publicKey); } } catch (e) { log.error("Could not calculate peer id for ENR", e); } return enr; } get nodeId() { switch (this.id) { case "v4": return this.publicKey ? v4.nodeId(this.publicKey) : undefined; default: throw new Error(ERR_INVALID_ID); } } getLocationMultiaddr = locationMultiaddrFromEnrFields.bind({}, this); get shardInfo() { if (this.rs && this.rsv) { log.warn("ENR contains both `rs` and `rsv` fields."); } return this.rs || this.rsv; } setLocationMultiaddr(multiaddr) { const protoNames = multiaddr.protoNames(); if (protoNames.length !== 2 && protoNames[1] !== "udp" && protoNames[1] !== "tcp") { throw new Error("Invalid multiaddr"); } const tuples = multiaddr.tuples(); if (!tuples[0][1] || !tuples[1][1]) { throw new Error("Invalid multiaddr"); } // IPv4 if (tuples[0][0] === 4) { this.set("ip", tuples[0][1]); this.set(protoNames[1], tuples[1][1]); } else { this.set("ip6", tuples[0][1]); this.set(protoNames[1] + "6", tuples[1][1]); } } getAllLocationMultiaddrs() { const multiaddrs = []; for (const protocol of Object.values(TransportProtocolPerIpVersion)) { const ma = this.getLocationMultiaddr(protocol); if (ma) multiaddrs.push(ma); } const _multiaddrs = this.multiaddrs ?? []; return multiaddrs.concat(_multiaddrs).map((ma) => { if (this.peerId) { return ma.encapsulate(`/p2p/${this.peerId.toString()}`); } return ma; }); } get peerInfo() { const id = this.peerId; if (!id) return; return { id, multiaddrs: this.getAllLocationMultiaddrs() }; } /** * Returns the full multiaddr from the ENR fields matching the provided * `protocol` parameter. * To return full multiaddrs from the `multiaddrs` ENR field, * use { @link ENR.getFullMultiaddrs }. * * @param protocol */ getFullMultiaddr(protocol) { if (this.peerId) { const locationMultiaddr = this.getLocationMultiaddr(protocol); if (locationMultiaddr) { return locationMultiaddr.encapsulate(`/p2p/${this.peerId.toString()}`); } } return; } /** * Returns the full multiaddrs from the `multiaddrs` ENR field. */ getFullMultiaddrs() { if (this.peerId && this.multiaddrs) { const peerId = this.peerId; return this.multiaddrs.map((ma) => { return ma.encapsulate(`/p2p/${peerId.toString()}`); }); } return []; } verify(data, signature) { if (!this.get("id") || this.id !== "v4") { throw new Error(ERR_INVALID_ID); } if (!this.publicKey) { throw new Error("Failed to verify ENR: No public key"); } return verifySignature(signature, keccak256(data), this.publicKey); } async sign(data, privateKey) { switch (this.id) { case "v4": this.signature = await v4.sign(privateKey, data); break; default: throw new Error(ERR_INVALID_ID); } return this.signature; } } //# sourceMappingURL=enr.js.map