diff --git a/CHANGELOG.md b/CHANGELOG.md index 127de76ec7..a939d188e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed +- Upgrade libp2p libraries: @chainsafe/libp2p-noise@4.1.1, libp2p@0.32.4, libp2p-gossipsub@0.11.1. +- Connects to a limited number of bootstrap nodes, defaults to 1. + +## [0.12.1] - 2021-09-16 + +### Changed +- **hot fix**: Connects to a limited number of bootstrap nodes, defaults to 1. + ## [0.12.0] - 2021-09-2 ### Added @@ -213,6 +222,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [Typedoc Documentation](https://status-im.github.io/js-waku/docs). [Unreleased]: https://github.com/status-im/js-waku/compare/v0.12.0...HEAD +[0.12.1]: https://github.com/status-im/js-waku/compare/v0.12.0...v0.12.1 [0.12.0]: https://github.com/status-im/js-waku/compare/v0.11.0...v0.12.0 [0.11.0]: https://github.com/status-im/js-waku/compare/v0.10.0...v0.11.0 [0.10.0]: https://github.com/status-im/js-waku/compare/v0.9.0...v0.10.0 diff --git a/package-lock.json b/package-lock.json index 3a6ffc5d24..b0f6d8f9fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "js-waku", - "version": "0.12.0", + "version": "0.12.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "js-waku", - "version": "0.12.0", + "version": "0.12.1", "license": "MIT OR Apache-2.0", "dependencies": { "@chainsafe/libp2p-noise": "^4.0.0", diff --git a/package.json b/package.json index 57c4219983..8979ebf176 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "js-waku", - "version": "0.12.0", + "version": "0.12.1", "description": "TypeScript implementation of the Waku v2 protocol", "main": "build/main/index.js", "typings": "build/main/index.d.ts", diff --git a/src/lib/discovery.browser.spec.ts b/src/lib/discovery.browser.spec.ts new file mode 100644 index 0000000000..ff4b7a7fa2 --- /dev/null +++ b/src/lib/discovery.browser.spec.ts @@ -0,0 +1,35 @@ +import { expect } from 'chai'; + +import { getPseudoRandomSubset } from './discovery'; + +describe('Discovery', () => { + it('returns all values when wanted number matches available values', function () { + const values = ['a', 'b', 'c']; + + const res = getPseudoRandomSubset(values, 3); + + expect(res.length).to.eq(3); + expect(res.includes('a')).to.be.true; + expect(res.includes('b')).to.be.true; + expect(res.includes('c')).to.be.true; + }); + + it('returns all values when wanted number is greater than available values', function () { + const values = ['a', 'b', 'c']; + + const res = getPseudoRandomSubset(values, 5); + + expect(res.length).to.eq(3); + expect(res.includes('a')).to.be.true; + expect(res.includes('b')).to.be.true; + expect(res.includes('c')).to.be.true; + }); + + it('returns a subset of values when wanted number is lesser than available values', function () { + const values = ['a', 'b', 'c']; + + const res = getPseudoRandomSubset(values, 2); + + expect(res.length).to.eq(2); + }); +}); diff --git a/src/lib/discovery.ts b/src/lib/discovery.ts index 4999bdcb33..327bb236ee 100644 --- a/src/lib/discovery.ts +++ b/src/lib/discovery.ts @@ -1,8 +1,11 @@ import axios from 'axios'; import debug from 'debug'; +import { shuffle } from 'libp2p-gossipsub/src/utils'; const dbg = debug('waku:discovery'); +const DefaultWantedNumber = 1; + /** * GET list of nodes from remote HTTP host. * @@ -14,6 +17,7 @@ const dbg = debug('waku:discovery'); * request returns `{ foo: { bar: [address1, address2] } }` then `path` should be * `[ "foo", "bar" ]`. * @param url Remote host containing bootstrap peers in JSON format. + * @param wantedNumber The number of connections desired. Defaults to [DefaultWantedNumber]. * * @returns An array of multiaddresses. * @throws If the remote host is unreachable or the response cannot be parsed @@ -21,8 +25,13 @@ const dbg = debug('waku:discovery'); */ export async function getBootstrapNodes( path: string[] = ['fleets', 'wakuv2.prod', 'waku-websocket'], - url = 'https://fleets.status.im/' + url = 'https://fleets.status.im/', + wantedNumber: number = DefaultWantedNumber ): Promise { + if (wantedNumber <= 0) { + return []; + } + const res = await axios.get(url, { headers: { 'Content-Type': 'application/json' }, }); @@ -43,7 +52,7 @@ export async function getBootstrapNodes( } if (Array.isArray(nodes)) { - return nodes; + return getPseudoRandomSubset(nodes, wantedNumber); } if (typeof nodes === 'string') { @@ -51,10 +60,22 @@ export async function getBootstrapNodes( } if (typeof nodes === 'object') { - return Object.values(nodes); + nodes = Object.values(nodes); + getPseudoRandomSubset(nodes, wantedNumber); } throw `Failed to retrieve bootstrap nodes: response format is not supported: ${JSON.stringify( nodes )}`; } + +export function getPseudoRandomSubset( + values: string[], + wantedNumber: number +): string[] { + if (values.length <= wantedNumber) { + return values; + } + + return shuffle(values).slice(0, wantedNumber); +}