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.
This commit is contained in:
fryorcraken.eth 2023-04-03 15:59:07 +10:00
parent e385652411
commit 1dd32101ba
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
9 changed files with 70 additions and 46 deletions

8
package-lock.json generated
View File

@ -29124,6 +29124,10 @@
"eslint-plugin-functional": "^5.0.4", "eslint-plugin-functional": "^5.0.4",
"eslint-plugin-import": "^2.27.5", "eslint-plugin-import": "^2.27.5",
"eslint-plugin-prettier": "^4.2.1", "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", "mocha": "^10.2.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^2.8.4", "prettier": "^2.8.4",
@ -34119,6 +34123,10 @@
"eslint-plugin-import": "^2.27.5", "eslint-plugin-import": "^2.27.5",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
"hi-base32": "^0.5.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", "mocha": "^10.2.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^2.8.4", "prettier": "^2.8.4",

View File

@ -4,9 +4,9 @@ const webpack = require("webpack");
module.exports = function (config) { module.exports = function (config) {
config.set({ config.set({
frameworks: ["webpack", "mocha"], frameworks: ["webpack", "mocha"],
files: ["src/**/*.ts"], files: ["src/**/!(node).spec.ts"],
preprocessors: { preprocessors: {
"src/**/*.ts": ["webpack"], "src/**/!(node).spec.ts": ["webpack"],
}, },
envPreprocessor: ["CI"], envPreprocessor: ["CI"],
reporters: ["progress"], reporters: ["progress"],
@ -20,7 +20,19 @@ module.exports = function (config) {
webpack: { webpack: {
mode: "development", mode: "development",
module: { module: {
rules: [{ test: /\.([cm]?ts|tsx)$/, loader: "ts-loader" }], rules: [
{
test: /\.([cm]?ts|tsx)$/,
use: [
{
loader: "ts-loader",
options: {
configFile: "tsconfig.karma.json",
},
},
],
},
],
}, },
plugins: [ plugins: [
new webpack.DefinePlugin({ new webpack.DefinePlugin({

View File

@ -53,7 +53,8 @@
"prepublish": "npm run build", "prepublish": "npm run build",
"reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build", "reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build",
"test": "run-s test:*", "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": { "engines": {
"node": ">=16" "node": ">=16"
@ -90,6 +91,10 @@
"eslint-plugin-functional": "^5.0.4", "eslint-plugin-functional": "^5.0.4",
"eslint-plugin-import": "^2.27.5", "eslint-plugin-import": "^2.27.5",
"eslint-plugin-prettier": "^4.2.1", "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", "mocha": "^10.2.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^2.8.4", "prettier": "^2.8.4",

View File

@ -273,7 +273,7 @@ describe("DNS Node Discovery [live data]", function () {
it(`should retrieve ${maxQuantity} multiaddrs for test.waku.nodes.status.im`, async function () { it(`should retrieve ${maxQuantity} multiaddrs for test.waku.nodes.status.im`, async function () {
this.timeout(10000); this.timeout(10000);
// Google's dns server address. Needs to be set explicitly to run in CI // 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], { const peers = await dnsNodeDiscovery.getPeers([enrTree.TEST], {
relay: maxQuantity, relay: maxQuantity,
store: 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 () { it(`should retrieve ${maxQuantity} multiaddrs for prod.waku.nodes.status.im`, async function () {
this.timeout(10000); this.timeout(10000);
// Google's dns server address. Needs to be set explicitly to run in CI // 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], { const peers = await dnsNodeDiscovery.getPeers([enrTree.PROD], {
relay: maxQuantity, relay: maxQuantity,
store: maxQuantity, store: maxQuantity,

View File

@ -33,9 +33,11 @@ export class DnsNodeDiscovery {
private readonly _DNSTreeCache: { [key: string]: string }; private readonly _DNSTreeCache: { [key: string]: string };
private readonly _errorTolerance: number = 10; private readonly _errorTolerance: number = 10;
public static dnsOverHttp(dnsClient?: DnsClient): DnsNodeDiscovery { public static async dnsOverHttp(
dnsClient?: DnsClient
): Promise<DnsNodeDiscovery> {
if (!dnsClient) { if (!dnsClient) {
dnsClient = new DnsOverHttps(); dnsClient = await DnsOverHttps.create();
} }
return new DnsNodeDiscovery(dnsClient); return new DnsNodeDiscovery(dnsClient);
} }

View File

@ -1,45 +1,32 @@
import { bytesToUtf8 } from "@waku/utils/bytes"; import { bytesToUtf8 } from "@waku/utils/bytes";
import debug from "debug"; import debug from "debug";
import { Endpoint, query, toEndpoint } from "dns-query"; import { Endpoint, query, wellknown } from "dns-query";
import { DnsClient } from "./dns.js"; import { DnsClient } from "./dns.js";
const log = debug("waku:dns-over-https"); const log = debug("waku:dns-over-https");
export class DnsOverHttps implements DnsClient { 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. * Create new Dns-Over-Http DNS client.
* *
* @param endpoints The endpoints for Dns-Over-Https queries; * @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. * @param retries Retries if a given endpoint fails.
* *
* @throws {code: string} If DNS query fails. * @throws {code: string} If DNS query fails.
*/ */
public constructor( public static async create(
private endpoints: Endpoint[] = DnsOverHttps.DefaultEndpoints, endpoints?: Endpoint[],
retries?: number
): Promise<DnsOverHttps> {
const _endpoints = endpoints ?? (await wellknown.endpoints("doh"));
return new DnsOverHttps(_endpoints, retries);
}
private constructor(
private endpoints: Endpoint[],
private retries: number = 3 private retries: number = 3
) {} ) {}

View File

@ -60,7 +60,7 @@ export class PeerDiscoveryDns
extends EventEmitter<PeerDiscoveryEvents> extends EventEmitter<PeerDiscoveryEvents>
implements PeerDiscovery implements PeerDiscovery
{ {
private readonly nextPeer: () => AsyncGenerator<IEnr>; private nextPeer: (() => AsyncGenerator<IEnr>) | undefined;
private _started: boolean; private _started: boolean;
private _components: DnsDiscoveryComponents; private _components: DnsDiscoveryComponents;
private _options: Options; private _options: Options;
@ -71,17 +71,8 @@ export class PeerDiscoveryDns
this._components = components; this._components = components;
this._options = options; this._options = options;
const { enrUrl, wantedNodeCapabilityCount } = options; const { enrUrl } = options;
log("Use following EIP-1459 ENR Tree URL: ", enrUrl); 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"); log("Starting peer discovery via dns");
this._started = true; 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()) { for await (const peer of this.nextPeer()) {
if (!this._started) return; if (!this._started) return;

View File

@ -0,0 +1,7 @@
{
"extends": "./tsconfig",
"compilerOptions": {
"module": "esnext"
},
"exclude": []
}

View File

@ -90,7 +90,7 @@ describe("DNS Node Discovery [live data]", function () {
this.timeout(10000); this.timeout(10000);
// Google's dns server address. Needs to be set explicitly to run in CI // 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"]], { const peers = await dnsNodeDiscovery.getPeers([enrTree["PROD"]], {
relay: maxQuantity, relay: maxQuantity,