Make parseBootstrap a class

Makes it easier to use the resulting function and document defaults.
This commit is contained in:
Franck Royer 2022-01-13 16:04:57 +11:00
parent ae0faa2146
commit fa4e94750f
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
3 changed files with 60 additions and 51 deletions

View File

@ -7,10 +7,6 @@ import { getNodesFromHostedJson, getPseudoRandomSubset } from './index';
const dbg = debug('waku:discovery:bootstrap'); const dbg = debug('waku:discovery:bootstrap');
export const DefaultMaxPeers = 1;
export type BootstrapFn = () => Promise<Multiaddr[]>;
/** /**
* Setup discovery method used to bootstrap. * 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. * The maximum of peers to connect to as part of the bootstrap process.
* *
* @default [[DefaultMaxPeers]] * @default [[Bootstrap.DefaultMaxPeers]]
*/ */
maxPeers?: number; 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 { export class Bootstrap {
const maxPeers = opts.maxPeers ?? DefaultMaxPeers; public static DefaultMaxPeers = 1;
if (opts.default) { public readonly getBootstrapPeers: (() => Promise<Multiaddr[]>) | undefined;
dbg('Bootstrap: Use hosted list of peers.');
return getNodesFromHostedJson.bind({}, undefined, undefined, maxPeers); constructor(opts: BootstrapOptions) {
} else if (opts.peers !== undefined && opts.peers.length > 0) { const maxPeers = opts.maxPeers ?? Bootstrap.DefaultMaxPeers;
dbg('Bootstrap: Use provided list of peers.');
const allPeers: Multiaddr[] = opts.peers.map( if (opts.default) {
(node: string) => new Multiaddr(node) dbg('Bootstrap: Use hosted list of peers.');
);
const peers = getPseudoRandomSubset(allPeers, maxPeers);
return (): Promise<Multiaddr[]> => Promise.resolve(peers);
} else if (typeof opts.getPeers === 'function') {
dbg('Bootstrap: Use provided getPeers function.');
const getPeers = opts.getPeers;
return async (): Promise<Multiaddr[]> => { this.getBootstrapPeers = getNodesFromHostedJson.bind(
const allPeers = await getPeers(); {},
return getPseudoRandomSubset<string | Multiaddr>(allPeers, maxPeers).map( undefined,
(node) => new Multiaddr(node) undefined,
maxPeers
); );
}; } else if (opts.peers !== undefined && opts.peers.length > 0) {
} else if (opts.enrUrl) { dbg('Bootstrap: Use provided list of peers.');
const enrUrl = opts.enrUrl;
dbg('Bootstrap: Use provided EIP-1459 ENR Tree URL.');
const dns = DnsNodeDiscovery.dnsOverHttp(); const allPeers: Multiaddr[] = opts.peers.map(
(node: string) => new Multiaddr(node)
);
const peers = getPseudoRandomSubset(allPeers, maxPeers);
this.getBootstrapPeers = (): Promise<Multiaddr[]> =>
Promise.resolve(peers);
} else if (typeof opts.getPeers === 'function') {
dbg('Bootstrap: Use provided getPeers function.');
const getPeers = opts.getPeers;
return async (): Promise<Multiaddr[]> => { this.getBootstrapPeers = async (): Promise<Multiaddr[]> => {
const enrs = await dns.getPeers(maxPeers, [enrUrl]); const allPeers = await getPeers();
const addresses: Multiaddr[] = []; return getPseudoRandomSubset<string | Multiaddr>(
enrs.forEach((enr) => { allPeers,
if (!enr.multiaddrs) return; 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) => { const dns = DnsNodeDiscovery.dnsOverHttp();
// Only return secure websocket addresses
if (ma.protoNames().includes('wss')) { this.getBootstrapPeers = async (): Promise<Multiaddr[]> => {
addresses.push(ma); 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;
return addresses; };
}; } else {
} else { dbg('No bootstrap method specified, no peer will be returned');
dbg('No bootstrap method specified, no peer will be returned'); this.getBootstrapPeers = undefined;
return (): Promise<Multiaddr[]> => Promise.resolve([]); }
} }
} }

View File

@ -1,7 +1,7 @@
import { shuffle } from 'libp2p-gossipsub/src/utils'; import { shuffle } from 'libp2p-gossipsub/src/utils';
export { getNodesFromHostedJson } from './hosted_json'; export { getNodesFromHostedJson } from './hosted_json';
export { parseBootstrap, BootstrapOptions, BootstrapFn } from './bootstrap'; export { Bootstrap, BootstrapOptions } from './bootstrap';
export { DnsClient, DnsNodeDiscovery } from './dns'; export { DnsClient, DnsNodeDiscovery } from './dns';
export { Endpoints, DnsOverHttps } from './dns_over_https'; export { Endpoints, DnsOverHttps } from './dns_over_https';
export { ENRTree } from './enrtree'; export { ENRTree } from './enrtree';

View File

@ -18,7 +18,7 @@ import Ping from 'libp2p/src/ping';
import { Multiaddr, multiaddr } from 'multiaddr'; import { Multiaddr, multiaddr } from 'multiaddr';
import PeerId from 'peer-id'; import PeerId from 'peer-id';
import { parseBootstrap } from './discovery'; import { Bootstrap } from './discovery';
import { BootstrapOptions } from './discovery/bootstrap'; import { BootstrapOptions } from './discovery/bootstrap';
import { getPeersForProtocol } from './select_peer'; import { getPeersForProtocol } from './select_peer';
import { LightPushCodec, WakuLightPush } from './waku_light_push'; import { LightPushCodec, WakuLightPush } from './waku_light_push';
@ -187,11 +187,11 @@ export class Waku {
}); });
if (options?.bootstrap) { if (options?.bootstrap) {
const bootstrap = parseBootstrap(options?.bootstrap); const bootstrap = new Bootstrap(options?.bootstrap);
if (bootstrap !== undefined) { if (bootstrap.getBootstrapPeers !== undefined) {
try { try {
const list = await bootstrap(); const list = await bootstrap.getBootstrapPeers();
// Note: this overrides any other peer discover // Note: this overrides any other peer discover
libp2pOpts.modules = Object.assign(libp2pOpts.modules, { libp2pOpts.modules = Object.assign(libp2pOpts.modules, {