From 1dd32101baf2750527369f7f25981882aa1f9527 Mon Sep 17 00:00:00 2001 From: "fryorcraken.eth" Date: Mon, 3 Apr 2023 15:59:07 +1000 Subject: [PATCH] fix(dns-discovery): Use DOH list from dns-query To make the library more robust as not all DOH allow CORS. Previous default DOH got CORS disabled. --- package-lock.json | 8 ++++ packages/dns-discovery/karma.conf.cjs | 18 +++++++-- packages/dns-discovery/package.json | 7 +++- packages/dns-discovery/src/dns.spec.ts | 4 +- packages/dns-discovery/src/dns.ts | 6 ++- packages/dns-discovery/src/dns_over_https.ts | 39 +++++++------------ packages/dns-discovery/src/index.ts | 25 ++++++------ packages/dns-discovery/tsconfig.karma.json | 7 ++++ .../tests/tests/dns-peer-discovery.spec.ts | 2 +- 9 files changed, 70 insertions(+), 46 deletions(-) create mode 100644 packages/dns-discovery/tsconfig.karma.json diff --git a/package-lock.json b/package-lock.json index d489e53d34..de413749c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29124,6 +29124,10 @@ "eslint-plugin-functional": "^5.0.4", "eslint-plugin-import": "^2.27.5", "eslint-plugin-prettier": "^4.2.1", + "karma": "^6.4.1", + "karma-chrome-launcher": "^3.1.1", + "karma-mocha": "^2.0.1", + "karma-webpack": "^5.0.0", "mocha": "^10.2.0", "npm-run-all": "^4.1.5", "prettier": "^2.8.4", @@ -34119,6 +34123,10 @@ "eslint-plugin-import": "^2.27.5", "eslint-plugin-prettier": "^4.2.1", "hi-base32": "^0.5.1", + "karma": "^6.4.1", + "karma-chrome-launcher": "^3.1.1", + "karma-mocha": "^2.0.1", + "karma-webpack": "^5.0.0", "mocha": "^10.2.0", "npm-run-all": "^4.1.5", "prettier": "^2.8.4", diff --git a/packages/dns-discovery/karma.conf.cjs b/packages/dns-discovery/karma.conf.cjs index 8ee5033706..31a1e477c3 100644 --- a/packages/dns-discovery/karma.conf.cjs +++ b/packages/dns-discovery/karma.conf.cjs @@ -4,9 +4,9 @@ const webpack = require("webpack"); module.exports = function (config) { config.set({ frameworks: ["webpack", "mocha"], - files: ["src/**/*.ts"], + files: ["src/**/!(node).spec.ts"], preprocessors: { - "src/**/*.ts": ["webpack"], + "src/**/!(node).spec.ts": ["webpack"], }, envPreprocessor: ["CI"], reporters: ["progress"], @@ -20,7 +20,19 @@ module.exports = function (config) { webpack: { mode: "development", module: { - rules: [{ test: /\.([cm]?ts|tsx)$/, loader: "ts-loader" }], + rules: [ + { + test: /\.([cm]?ts|tsx)$/, + use: [ + { + loader: "ts-loader", + options: { + configFile: "tsconfig.karma.json", + }, + }, + ], + }, + ], }, plugins: [ new webpack.DefinePlugin({ diff --git a/packages/dns-discovery/package.json b/packages/dns-discovery/package.json index 06c97932b1..552975a0d7 100644 --- a/packages/dns-discovery/package.json +++ b/packages/dns-discovery/package.json @@ -53,7 +53,8 @@ "prepublish": "npm run build", "reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build", "test": "run-s test:*", - "test:node": "TS_NODE_PROJECT=./tsconfig.dev.json mocha" + "test:node": "TS_NODE_PROJECT=./tsconfig.dev.json mocha", + "test:browser": "karma start karma.conf.cjs" }, "engines": { "node": ">=16" @@ -90,6 +91,10 @@ "eslint-plugin-functional": "^5.0.4", "eslint-plugin-import": "^2.27.5", "eslint-plugin-prettier": "^4.2.1", + "karma": "^6.4.1", + "karma-chrome-launcher": "^3.1.1", + "karma-mocha": "^2.0.1", + "karma-webpack": "^5.0.0", "mocha": "^10.2.0", "npm-run-all": "^4.1.5", "prettier": "^2.8.4", diff --git a/packages/dns-discovery/src/dns.spec.ts b/packages/dns-discovery/src/dns.spec.ts index 2591a5e7f0..a68c016437 100644 --- a/packages/dns-discovery/src/dns.spec.ts +++ b/packages/dns-discovery/src/dns.spec.ts @@ -273,7 +273,7 @@ describe("DNS Node Discovery [live data]", function () { it(`should retrieve ${maxQuantity} multiaddrs for test.waku.nodes.status.im`, async function () { this.timeout(10000); // Google's dns server address. Needs to be set explicitly to run in CI - const dnsNodeDiscovery = DnsNodeDiscovery.dnsOverHttp(); + const dnsNodeDiscovery = await DnsNodeDiscovery.dnsOverHttp(); const peers = await dnsNodeDiscovery.getPeers([enrTree.TEST], { relay: maxQuantity, store: maxQuantity, @@ -296,7 +296,7 @@ describe("DNS Node Discovery [live data]", function () { it(`should retrieve ${maxQuantity} multiaddrs for prod.waku.nodes.status.im`, async function () { this.timeout(10000); // Google's dns server address. Needs to be set explicitly to run in CI - const dnsNodeDiscovery = DnsNodeDiscovery.dnsOverHttp(); + const dnsNodeDiscovery = await DnsNodeDiscovery.dnsOverHttp(); const peers = await dnsNodeDiscovery.getPeers([enrTree.PROD], { relay: maxQuantity, store: maxQuantity, diff --git a/packages/dns-discovery/src/dns.ts b/packages/dns-discovery/src/dns.ts index 41693b3204..8473d8648c 100644 --- a/packages/dns-discovery/src/dns.ts +++ b/packages/dns-discovery/src/dns.ts @@ -33,9 +33,11 @@ export class DnsNodeDiscovery { private readonly _DNSTreeCache: { [key: string]: string }; private readonly _errorTolerance: number = 10; - public static dnsOverHttp(dnsClient?: DnsClient): DnsNodeDiscovery { + public static async dnsOverHttp( + dnsClient?: DnsClient + ): Promise { if (!dnsClient) { - dnsClient = new DnsOverHttps(); + dnsClient = await DnsOverHttps.create(); } return new DnsNodeDiscovery(dnsClient); } diff --git a/packages/dns-discovery/src/dns_over_https.ts b/packages/dns-discovery/src/dns_over_https.ts index 1e0403ec9c..672a917666 100644 --- a/packages/dns-discovery/src/dns_over_https.ts +++ b/packages/dns-discovery/src/dns_over_https.ts @@ -1,45 +1,32 @@ import { bytesToUtf8 } from "@waku/utils/bytes"; import debug from "debug"; -import { Endpoint, query, toEndpoint } from "dns-query"; +import { Endpoint, query, wellknown } from "dns-query"; import { DnsClient } from "./dns.js"; const log = debug("waku:dns-over-https"); export class DnsOverHttps implements DnsClient { - /** - * Default endpoints to use for DNS queries. - * Taken from https://github.com/martinheidegger/dns-query as static data - * to avoid dynamic queries. - * - * To dynamically retrieve other endpoints, use https://github.com/martinheidegger/dns-query#well-known-endpoints - */ - static DefaultEndpoints: Endpoint[] = [ - toEndpoint({ - name: "AhaDNS", - protocol: "https:", - host: "doh.la.ahadns.net", - ipv4: "45.67.219.208", - }), - toEndpoint({ - name: "cloudflare", - protocol: "https:", - host: "dns.cloudflare.com", - ipv4: "1.0.0.1", - }), - ]; - /** * Create new Dns-Over-Http DNS client. * * @param endpoints The endpoints for Dns-Over-Https queries; - * Defaults to [[DnsOverHttps.DefaultEndpoints]]. + * Defaults to using dns-query's API.. * @param retries Retries if a given endpoint fails. * * @throws {code: string} If DNS query fails. */ - public constructor( - private endpoints: Endpoint[] = DnsOverHttps.DefaultEndpoints, + public static async create( + endpoints?: Endpoint[], + retries?: number + ): Promise { + const _endpoints = endpoints ?? (await wellknown.endpoints("doh")); + + return new DnsOverHttps(_endpoints, retries); + } + + private constructor( + private endpoints: Endpoint[], private retries: number = 3 ) {} diff --git a/packages/dns-discovery/src/index.ts b/packages/dns-discovery/src/index.ts index 0151714c68..db4a15969b 100644 --- a/packages/dns-discovery/src/index.ts +++ b/packages/dns-discovery/src/index.ts @@ -60,7 +60,7 @@ export class PeerDiscoveryDns extends EventEmitter implements PeerDiscovery { - private readonly nextPeer: () => AsyncGenerator; + private nextPeer: (() => AsyncGenerator) | undefined; private _started: boolean; private _components: DnsDiscoveryComponents; private _options: Options; @@ -71,17 +71,8 @@ export class PeerDiscoveryDns this._components = components; this._options = options; - const { enrUrl, wantedNodeCapabilityCount } = options; - + const { enrUrl } = options; log("Use following EIP-1459 ENR Tree URL: ", enrUrl); - - const dns = DnsNodeDiscovery.dnsOverHttp(); - - this.nextPeer = dns.getNextPeer.bind( - dns, - [enrUrl], - wantedNodeCapabilityCount - ); } /** @@ -91,6 +82,18 @@ export class PeerDiscoveryDns log("Starting peer discovery via dns"); this._started = true; + + if (this.nextPeer === undefined) { + const { enrUrl, wantedNodeCapabilityCount } = this._options; + const dns = await DnsNodeDiscovery.dnsOverHttp(); + + this.nextPeer = dns.getNextPeer.bind( + dns, + [enrUrl], + wantedNodeCapabilityCount + ); + } + for await (const peer of this.nextPeer()) { if (!this._started) return; diff --git a/packages/dns-discovery/tsconfig.karma.json b/packages/dns-discovery/tsconfig.karma.json new file mode 100644 index 0000000000..eb6e3bcd34 --- /dev/null +++ b/packages/dns-discovery/tsconfig.karma.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig", + "compilerOptions": { + "module": "esnext" + }, + "exclude": [] +} diff --git a/packages/tests/tests/dns-peer-discovery.spec.ts b/packages/tests/tests/dns-peer-discovery.spec.ts index bbe4f860bd..4ddddde347 100644 --- a/packages/tests/tests/dns-peer-discovery.spec.ts +++ b/packages/tests/tests/dns-peer-discovery.spec.ts @@ -90,7 +90,7 @@ describe("DNS Node Discovery [live data]", function () { this.timeout(10000); // Google's dns server address. Needs to be set explicitly to run in CI - const dnsNodeDiscovery = DnsNodeDiscovery.dnsOverHttp(); + const dnsNodeDiscovery = await DnsNodeDiscovery.dnsOverHttp(); const peers = await dnsNodeDiscovery.getPeers([enrTree["PROD"]], { relay: maxQuantity,