diff --git a/src/lib/discovery/bootstrap.ts b/src/lib/discovery/bootstrap.ts index fda17a6f80..771eaad558 100644 --- a/src/lib/discovery/bootstrap.ts +++ b/src/lib/discovery/bootstrap.ts @@ -7,10 +7,6 @@ import { getNodesFromHostedJson, getPseudoRandomSubset } from './index'; const dbg = debug('waku:discovery:bootstrap'); -export const DefaultMaxPeers = 1; - -export type BootstrapFn = () => Promise; - /** * Setup discovery method used to bootstrap. * @@ -20,7 +16,7 @@ export interface BootstrapOptions { /** * The maximum of peers to connect to as part of the bootstrap process. * - * @default [[DefaultMaxPeers]] + * @default [[Bootstrap.DefaultMaxPeers]] */ maxPeers?: number; /** @@ -48,56 +44,69 @@ export interface BootstrapOptions { } /** - * Parse the bootstrap options and returns an async function that returns node addresses upon invocation. + * Parse options and expose function to return bootstrap peer addresses. */ -export function parseBootstrap(opts: BootstrapOptions): BootstrapFn { - const maxPeers = opts.maxPeers ?? DefaultMaxPeers; +export class Bootstrap { + public static DefaultMaxPeers = 1; - if (opts.default) { - dbg('Bootstrap: Use hosted list of peers.'); + public readonly getBootstrapPeers: (() => Promise) | undefined; - return getNodesFromHostedJson.bind({}, undefined, undefined, maxPeers); - } else if (opts.peers !== undefined && opts.peers.length > 0) { - dbg('Bootstrap: Use provided list of peers.'); + constructor(opts: BootstrapOptions) { + const maxPeers = opts.maxPeers ?? Bootstrap.DefaultMaxPeers; - const allPeers: Multiaddr[] = opts.peers.map( - (node: string) => new Multiaddr(node) - ); - const peers = getPseudoRandomSubset(allPeers, maxPeers); - return (): Promise => Promise.resolve(peers); - } else if (typeof opts.getPeers === 'function') { - dbg('Bootstrap: Use provided getPeers function.'); - const getPeers = opts.getPeers; + if (opts.default) { + dbg('Bootstrap: Use hosted list of peers.'); - return async (): Promise => { - const allPeers = await getPeers(); - return getPseudoRandomSubset(allPeers, maxPeers).map( - (node) => new Multiaddr(node) + this.getBootstrapPeers = getNodesFromHostedJson.bind( + {}, + undefined, + undefined, + maxPeers ); - }; - } else if (opts.enrUrl) { - const enrUrl = opts.enrUrl; - dbg('Bootstrap: Use provided EIP-1459 ENR Tree URL.'); + } else if (opts.peers !== undefined && opts.peers.length > 0) { + dbg('Bootstrap: Use provided list of peers.'); - const dns = DnsNodeDiscovery.dnsOverHttp(); + const allPeers: Multiaddr[] = opts.peers.map( + (node: string) => new Multiaddr(node) + ); + const peers = getPseudoRandomSubset(allPeers, maxPeers); + this.getBootstrapPeers = (): Promise => + Promise.resolve(peers); + } else if (typeof opts.getPeers === 'function') { + dbg('Bootstrap: Use provided getPeers function.'); + const getPeers = opts.getPeers; - return async (): Promise => { - const enrs = await dns.getPeers(maxPeers, [enrUrl]); - const addresses: Multiaddr[] = []; - enrs.forEach((enr) => { - if (!enr.multiaddrs) return; + this.getBootstrapPeers = async (): Promise => { + const allPeers = await getPeers(); + return getPseudoRandomSubset( + allPeers, + maxPeers + ).map((node) => new Multiaddr(node)); + }; + } else if (opts.enrUrl) { + const enrUrl = opts.enrUrl; + dbg('Bootstrap: Use provided EIP-1459 ENR Tree URL.'); - enr.multiaddrs.forEach((ma: Multiaddr) => { - // Only return secure websocket addresses - if (ma.protoNames().includes('wss')) { - addresses.push(ma); - } + const dns = DnsNodeDiscovery.dnsOverHttp(); + + this.getBootstrapPeers = async (): Promise => { + const enrs = await dns.getPeers(maxPeers, [enrUrl]); + const addresses: Multiaddr[] = []; + enrs.forEach((enr) => { + if (!enr.multiaddrs) return; + + enr.multiaddrs.forEach((ma: Multiaddr) => { + // Only return secure websocket addresses + if (ma.protoNames().includes('wss')) { + addresses.push(ma); + } + }); }); - }); - return addresses; - }; - } else { - dbg('No bootstrap method specified, no peer will be returned'); - return (): Promise => Promise.resolve([]); + return addresses; + }; + } else { + dbg('No bootstrap method specified, no peer will be returned'); + this.getBootstrapPeers = undefined; + } } } diff --git a/src/lib/discovery/index.ts b/src/lib/discovery/index.ts index b0e04fd44d..d18088a0d4 100644 --- a/src/lib/discovery/index.ts +++ b/src/lib/discovery/index.ts @@ -1,7 +1,7 @@ import { shuffle } from 'libp2p-gossipsub/src/utils'; export { getNodesFromHostedJson } from './hosted_json'; -export { parseBootstrap, BootstrapOptions, BootstrapFn } from './bootstrap'; +export { Bootstrap, BootstrapOptions } from './bootstrap'; export { DnsClient, DnsNodeDiscovery } from './dns'; export { Endpoints, DnsOverHttps } from './dns_over_https'; export { ENRTree } from './enrtree'; diff --git a/src/lib/waku.ts b/src/lib/waku.ts index aaa83636e5..977b07c19b 100644 --- a/src/lib/waku.ts +++ b/src/lib/waku.ts @@ -18,7 +18,7 @@ import Ping from 'libp2p/src/ping'; import { Multiaddr, multiaddr } from 'multiaddr'; import PeerId from 'peer-id'; -import { parseBootstrap } from './discovery'; +import { Bootstrap } from './discovery'; import { BootstrapOptions } from './discovery/bootstrap'; import { getPeersForProtocol } from './select_peer'; import { LightPushCodec, WakuLightPush } from './waku_light_push'; @@ -187,11 +187,11 @@ export class Waku { }); if (options?.bootstrap) { - const bootstrap = parseBootstrap(options?.bootstrap); + const bootstrap = new Bootstrap(options?.bootstrap); - if (bootstrap !== undefined) { + if (bootstrap.getBootstrapPeers !== undefined) { try { - const list = await bootstrap(); + const list = await bootstrap.getBootstrapPeers(); // Note: this overrides any other peer discover libp2pOpts.modules = Object.assign(libp2pOpts.modules, {