From 4ccd82b6f1009ea901d107f73712211c81704f04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Thu, 31 Oct 2019 13:20:40 +0100 Subject: [PATCH 1/8] feat: websocket-star? what's that. only heard of stardust! (...psst, we're replacing ws-star with stardust, which does the same things, except it's way faster & more secure) --- README.md | 8 +++++--- examples/circuit-relaying/README.md | 2 +- examples/custom-libp2p/index.js | 10 +++++----- examples/custom-libp2p/package.json | 2 +- examples/exchange-files-in-browser/public/app.js | 2 +- package-list.json | 2 +- package.json | 4 ++-- src/core/runtime/libp2p-browser.js | 8 -------- src/core/runtime/libp2p-nodejs.js | 10 +--------- test/core/libp2p.spec.js | 8 ++++---- 10 files changed, 21 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 908c21d2e8..b93986f52c 100644 --- a/README.md +++ b/README.md @@ -1003,22 +1003,24 @@ The code above assumes you are running a local `signaling server` on port `9090` #### Is there a more stable alternative to webrtc-star that offers a similar functionality? -Yes, websocket-star! A WebSockets based transport that uses a Relay to route the messages. To enable it, just do: +Yes, stardust! A WebSockets based transport that uses a Relay to route the messages. To enable it, just do: ```JavaScript const node = await IPFS.create({ config: { Addresses: { Swarm: [ - '/dns4/ws-star.discovery.libp2p.io/tcp/443/wss/p2p-websocket-star' + '/dns4/stardust.mkg20001.io/tcp/443/wss/p2p-stardust' ] } } }) -// your instance with websocket-star is ready +// your instance with stardust is ready ``` +(You may need to install the stardust module as well, with `npm install libp2p-stardust`) + #### I see some slowness when hopping between tabs Chrome with IPFS nodes, is there a reason why? Yes, unfortunately, due to [Chrome aggressive resource throttling policy](https://github.com/ipfs/js-ipfs/issues/611), it cuts freezes the execution of any background tab, turning an IPFS node that was running on that webpage into a vegetable state. diff --git a/examples/circuit-relaying/README.md b/examples/circuit-relaying/README.md index be33d79bab..6f84086acc 100644 --- a/examples/circuit-relaying/README.md +++ b/examples/circuit-relaying/README.md @@ -155,7 +155,7 @@ In order to enable the relay functionality in `go-ipfs` we need to edit it's con The two options we're looking for are `DisableRelay` and `EnableRelayHop`. We want the former (`DisableRelay`) set to `false` and the latter (`EnableRelayHop`) to `true`, just like in the example above. That should set our go node as a relay. -We also need to make sure our go node can be dialed from the browser. For that, we need to enable a transport that both the browser and the go node can communicate over. We will use the web sockets transport, although there are others that can be used, such as `webrtc-star` and `websocket-star`. To enable the transport and set the interface and port we need to edit the `~/.ipfs/config` one more time. Let's find the `Swarm` array and add our desired address there. I picked `/ip4/0.0.0.0/tcp/4004/ws` because it is a port I know is not being used by anything on my machine, but we can also use port `0` so that the OS chooses a random available port for us — either one should work. +We also need to make sure our go node can be dialed from the browser. For that, we need to enable a transport that both the browser and the go node can communicate over. We will use the web sockets transport, although there are others that can be used, such as `webrtc-star` and `stardust`. To enable the transport and set the interface and port we need to edit the `~/.ipfs/config` one more time. Let's find the `Swarm` array and add our desired address there. I picked `/ip4/0.0.0.0/tcp/4004/ws` because it is a port I know is not being used by anything on my machine, but we can also use port `0` so that the OS chooses a random available port for us — either one should work. ```json "Swarm": [ diff --git a/examples/custom-libp2p/index.js b/examples/custom-libp2p/index.js index fa1a097b86..d4f038041d 100644 --- a/examples/custom-libp2p/index.js +++ b/examples/custom-libp2p/index.js @@ -4,7 +4,7 @@ const Libp2p = require('libp2p') const IPFS = require('ipfs') const TCP = require('libp2p-tcp') const MulticastDNS = require('libp2p-mdns') -const WebSocketStar = require('libp2p-websocket-star') +const Stardust = require('libp2p-stardust') const Bootstrap = require('libp2p-bootstrap') const SPDY = require('libp2p-spdy') const KadDHT = require('libp2p-kad-dht') @@ -32,8 +32,8 @@ const libp2pBundle = (opts) => { const peerBook = opts.peerBook const bootstrapList = opts.config.Bootstrap - // Create our WebSocketStar transport and give it our PeerId, straight from the ipfs node - const wsstar = new WebSocketStar({ + // Create our Stardust transport and give it our PeerId, straight from the ipfs node + const stardust = new Stardust({ id: peerInfo.id }) @@ -50,7 +50,7 @@ const libp2pBundle = (opts) => { modules: { transport: [ TCP, - wsstar + stardust ], streamMuxer: [ MPLEX, @@ -62,7 +62,7 @@ const libp2pBundle = (opts) => { peerDiscovery: [ MulticastDNS, Bootstrap, - wsstar.discovery + stardust.discovery ], dht: KadDHT }, diff --git a/examples/custom-libp2p/package.json b/examples/custom-libp2p/package.json index 904579511e..9da7b5d344 100644 --- a/examples/custom-libp2p/package.json +++ b/examples/custom-libp2p/package.json @@ -17,7 +17,7 @@ "libp2p-secio": "~0.11.1", "libp2p-spdy": "~0.13.3", "libp2p-tcp": "~0.13.0", - "libp2p-websocket-star": "~0.10.2", + "libp2p-stardust": "~0.1.2", "pull-mplex": "~0.1.0" } } diff --git a/examples/exchange-files-in-browser/public/app.js b/examples/exchange-files-in-browser/public/app.js index f23ca84f14..11fa4f5d55 100644 --- a/examples/exchange-files-in-browser/public/app.js +++ b/examples/exchange-files-in-browser/public/app.js @@ -48,7 +48,7 @@ async function start () { repo: 'ipfs-' + Math.random(), config: { Addresses: { - Swarm: ['/dns4/ws-star.discovery.libp2p.io/tcp/443/wss/p2p-websocket-star'] + Swarm: ['/dns4/stardust.mkg20001.io/tcp/443/wss/p2p-stardust'] } } } diff --git a/package-list.json b/package-list.json index efd98007cc..94ab5e2a9e 100644 --- a/package-list.json +++ b/package-list.json @@ -49,8 +49,8 @@ ["libp2p/js-libp2p-bootstrap", "libp2p-bootstrap"], ["libp2p/js-libp2p-secio", "libp2p-secio"], ["libp2p/js-libp2p-tcp", "libp2p-tcp"], + ["libp2p/js-libp2p-stardust", "libp2p-stardust"], ["libp2p/js-libp2p-webrtc-star", "libp2p-webrtc-star"], - ["libp2p/js-libp2p-websocket-star", "libp2p-websocket-star"], ["libp2p/js-libp2p-websockets", "libp2p-websockets"], ["libp2p/pull-mplex", "pull-mplex"], diff --git a/package.json b/package.json index 4f08f4477d..dcdf1a775f 100644 --- a/package.json +++ b/package.json @@ -144,7 +144,6 @@ "libp2p-secio": "~0.11.0", "libp2p-tcp": "^0.13.0", "libp2p-webrtc-star": "~0.16.0", - "libp2p-websocket-star-multi": "~0.4.3", "libp2p-websockets": "~0.12.3", "lodash.flatten": "^4.4.0", "mafmt": "^6.0.10", @@ -207,7 +206,7 @@ "interface-ipfs-core": "^0.118.0", "ipfs-interop": "^0.1.1", "ipfsd-ctl": "^0.47.2", - "libp2p-websocket-star": "~0.10.2", + "libp2p-stardust": "~0.1.2", "lodash": "^4.17.15", "ncp": "^2.0.0", "p-event": "^4.1.0", @@ -359,3 +358,4 @@ "Максим Ильин " ] } + diff --git a/src/core/runtime/libp2p-browser.js b/src/core/runtime/libp2p-browser.js index 643fcf108f..70e1add67e 100644 --- a/src/core/runtime/libp2p-browser.js +++ b/src/core/runtime/libp2p-browser.js @@ -2,7 +2,6 @@ const WS = require('libp2p-websockets') const WebRTCStar = require('libp2p-webrtc-star') -const WebSocketStarMulti = require('libp2p-websocket-star-multi') const Multiplex = require('pull-mplex') const SECIO = require('libp2p-secio') const Bootstrap = require('libp2p-bootstrap') @@ -16,12 +15,6 @@ class Node extends libp2p { constructor (_options) { const wrtcstar = new WebRTCStar({ id: _options.peerInfo.id }) - // this can be replaced once optional listening is supported with the below code. ref: https://github.com/libp2p/interface-transport/issues/41 - // const wsstar = new WebSocketStar({ id: _options.peerInfo.id }) - const wsstarServers = _options.peerInfo.multiaddrs.toArray().map(String).filter(addr => addr.includes('p2p-websocket-star')) - _options.peerInfo.multiaddrs.replace(wsstarServers.map(multiaddr), '/p2p-websocket-star') // the ws-star-multi module will replace this with the chosen ws-star servers - const wsstar = new WebSocketStarMulti({ servers: wsstarServers, id: _options.peerInfo.id, ignore_no_online: !wsstarServers.length || _options.wsStarIgnoreErrors }) - const defaults = { switch: { denyTTL: 2 * 60 * 1e3, // 2 minute base @@ -44,7 +37,6 @@ class Node extends libp2p { ], peerDiscovery: [ wrtcstar.discovery, - wsstar.discovery, Bootstrap ], dht: KadDHT, diff --git a/src/core/runtime/libp2p-nodejs.js b/src/core/runtime/libp2p-nodejs.js index f124aa4c1f..9bd3d15ead 100644 --- a/src/core/runtime/libp2p-nodejs.js +++ b/src/core/runtime/libp2p-nodejs.js @@ -3,7 +3,6 @@ const TCP = require('libp2p-tcp') const MulticastDNS = require('libp2p-mdns') const WS = require('libp2p-websockets') -const WebSocketStarMulti = require('libp2p-websocket-star-multi') const Bootstrap = require('libp2p-bootstrap') const KadDHT = require('libp2p-kad-dht') const GossipSub = require('libp2p-gossipsub') @@ -15,12 +14,6 @@ const multiaddr = require('multiaddr') class Node extends libp2p { constructor (_options) { - // this can be replaced once optional listening is supported with the below code. ref: https://github.com/libp2p/interface-transport/issues/41 - // const wsstar = new WebSocketStar({ id: _options.peerInfo.id }) - const wsstarServers = _options.peerInfo.multiaddrs.toArray().map(String).filter(addr => addr.includes('p2p-websocket-star')) - _options.peerInfo.multiaddrs.replace(wsstarServers.map(multiaddr), '/p2p-websocket-star') // the ws-star-multi module will replace this with the chosen ws-star servers - const wsstar = new WebSocketStarMulti({ servers: wsstarServers, id: _options.peerInfo.id, ignore_no_online: !wsstarServers.length || _options.wsStarIgnoreErrors }) - const defaults = { switch: { denyTTL: 2 * 60 * 1e3, // 2 minute base @@ -43,8 +36,7 @@ class Node extends libp2p { ], peerDiscovery: [ MulticastDNS, - Bootstrap, - wsstar.discovery + Bootstrap ], dht: KadDHT, pubsub: GossipSub diff --git a/test/core/libp2p.spec.js b/test/core/libp2p.spec.js index 139729dc36..c470f79d83 100644 --- a/test/core/libp2p.spec.js +++ b/test/core/libp2p.spec.js @@ -6,7 +6,7 @@ const { expect } = require('interface-ipfs-core/src/utils/mocha') const MemoryStore = require('interface-datastore').MemoryDatastore const PeerInfo = require('peer-info') const PeerBook = require('peer-book') -const WebSocketStar = require('libp2p-websocket-star') +const Stardust = require('libp2p-stardust') const Multiplex = require('pull-mplex') const SECIO = require('libp2p-secio') const KadDHT = require('libp2p-kad-dht') @@ -71,14 +71,14 @@ describe('libp2p customization', function () { _print: console.log, _options: { libp2p: (opts) => { - const wsstar = new WebSocketStar({ id: opts.peerInfo.id }) + const stardust = new Stardust({ id: opts.peerInfo.id }) return new Libp2p({ peerInfo: opts.peerInfo, peerBook: opts.peerBook, modules: { transport: [ - wsstar + stardust ], streamMuxer: [ Multiplex @@ -87,7 +87,7 @@ describe('libp2p customization', function () { SECIO ], peerDiscovery: [ - wsstar.discovery + stardust.discovery ], dht: KadDHT } From f48fcf9f75ede4b3d1df8eea296bcf9ca373ecc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Thu, 31 Oct 2019 13:44:10 +0100 Subject: [PATCH 2/8] feat: add .overrideFunction --- README.md | 3 +++ src/core/components/libp2p.js | 13 ++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b93986f52c..0e00fe8dee 100644 --- a/README.md +++ b/README.md @@ -537,6 +537,9 @@ The libp2p option allows you to build your libp2p node by configuration, or via You can see the bundle in action in the [custom libp2p example](examples/custom-libp2p). +- `overrideFunction` (object): + - A function that allows overriding parts of libp2p's config, using dynamic arguments, without fully replacing the bundle as a custom libp2p bundle would do + - It is called with the arguments `{ datastore, peerInfo, peerBook, options, config }` - `modules` (object): - `transport` (Array<[libp2p.Transport](https://github.com/libp2p/interface-transport)>): An array of Libp2p transport classes/instances to use _instead_ of the defaults. See [libp2p/interface-transport](https://github.com/libp2p/interface-transport) for details. - `peerDiscovery` (Array<[libp2p.PeerDiscovery](https://github.com/libp2p/interface-peer-discovery)>): An array of Libp2p peer discovery classes/instances to use _instead_ of the defaults. See [libp2p/peer-discovery](https://github.com/libp2p/interface-peer-discovery) for details. If passing a class, configuration can be passed using the config section below under the key corresponding to you module's unique `tag` (a static property on the class) diff --git a/src/core/components/libp2p.js b/src/core/components/libp2p.js index 35ddce54dc..5b4a47f84f 100644 --- a/src/core/components/libp2p.js +++ b/src/core/components/libp2p.js @@ -133,7 +133,18 @@ function defaultBundle ({ datastore, peerInfo, peerBook, options, config }) { }) } - const libp2pOptions = mergeOptions(libp2pDefaults, get(options, 'libp2p', {})) + const libp2pUserOptions = get(options, 'libp2p', {}) + + let libp2pOptions = libp2pDefaults + + // allow user to specify overrideFunction, while at the same time allowing static arguments + if (libp2pUserOptions.overrideFunction && typeof libp2pUserOptions.overrideFunction === 'function') { + libp2pOptions = mergeOptions(libp2pOptions, libp2pUserOptions.overrideFunction({ datastore, peerInfo, peerBook, options, config })) + delete libp2pUserOptions.overrideFunction + } + + libp2pOptions = mergeOptions(libp2pOptions, libp2pUserOptions) + // Required inline to reduce startup time // Note: libp2p-nodejs gets replaced by libp2p-browser when webpacked/browserified const Node = require('../runtime/libp2p-nodejs') From 95a96ad0d4214f0509713f0158777f2fe5b15538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Thu, 31 Oct 2019 13:56:53 +0100 Subject: [PATCH 3/8] feat: use stardust4ipfs --- README.md | 5 ++++- examples/exchange-files-in-browser/package.json | 3 ++- examples/exchange-files-in-browser/public/app.js | 7 +++++-- src/core/runtime/libp2p-nodejs.js | 4 +--- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 0e00fe8dee..2a34d383b3 100644 --- a/README.md +++ b/README.md @@ -1010,6 +1010,9 @@ Yes, stardust! A WebSockets based transport that uses a Relay to route the messa ```JavaScript const node = await IPFS.create({ + libp2p: { + overrideFunction: require('stardust4ipfs') + }, config: { Addresses: { Swarm: [ @@ -1022,7 +1025,7 @@ const node = await IPFS.create({ // your instance with stardust is ready ``` -(You may need to install the stardust module as well, with `npm install libp2p-stardust`) +(You may need to install the stardust4ipfs module as well, with `npm install stardust4ipfs`) #### I see some slowness when hopping between tabs Chrome with IPFS nodes, is there a reason why? diff --git a/examples/exchange-files-in-browser/package.json b/examples/exchange-files-in-browser/package.json index f2421f8793..fff6b934cc 100644 --- a/examples/exchange-files-in-browser/package.json +++ b/examples/exchange-files-in-browser/package.json @@ -9,7 +9,8 @@ "license": "MIT", "devDependencies": { "browserify": "^16.2.3", - "http-server": "~0.11.1" + "http-server": "~0.11.1", + "stardust4ipfs": "~0.1.1" }, "dependencies": { "ipfs": "file:../../" diff --git a/examples/exchange-files-in-browser/public/app.js b/examples/exchange-files-in-browser/public/app.js index 11fa4f5d55..3bfd4ff317 100644 --- a/examples/exchange-files-in-browser/public/app.js +++ b/examples/exchange-files-in-browser/public/app.js @@ -46,6 +46,9 @@ async function start () { if (!node) { const options = { repo: 'ipfs-' + Math.random(), + libp2p: { + overrideFunction: require('stardust4ipfs') + }, config: { Addresses: { Swarm: ['/dns4/stardust.mkg20001.io/tcp/443/wss/p2p-stardust'] @@ -154,7 +157,7 @@ const publishHash = (hash) => { const sendFileList = () => Promise.all(FILES.map(publishHash)) const updateProgress = (bytesLoaded) => { - let percent = 100 - ((bytesLoaded / fileSize) * 100) + const percent = 100 - ((bytesLoaded / fileSize) * 100) $progressBar.style.transform = `translateX(${-percent}%)` } @@ -261,7 +264,7 @@ async function connectToPeer (event) { await node.swarm.connect(multiaddr) - onSuccess(`Successfully connected to peer.`) + onSuccess('Successfully connected to peer.') $multiaddrInput.value = '' } diff --git a/src/core/runtime/libp2p-nodejs.js b/src/core/runtime/libp2p-nodejs.js index 9bd3d15ead..6485e2d8d5 100644 --- a/src/core/runtime/libp2p-nodejs.js +++ b/src/core/runtime/libp2p-nodejs.js @@ -10,7 +10,6 @@ const Multiplex = require('pull-mplex') const SECIO = require('libp2p-secio') const libp2p = require('libp2p') const mergeOptions = require('merge-options') -const multiaddr = require('multiaddr') class Node extends libp2p { constructor (_options) { @@ -25,8 +24,7 @@ class Node extends libp2p { modules: { transport: [ TCP, - WS, - wsstar + WS ], streamMuxer: [ Multiplex From 4f39db81fd3f1952062e5138708e94500312aa53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Thu, 31 Oct 2019 14:06:21 +0100 Subject: [PATCH 4/8] feat: stardust4ipfs tests --- package.json | 1 + src/core/runtime/libp2p-browser.js | 4 +--- test/core/libp2p.spec.js | 29 +++++++++++++++++++++++++++-- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index dcdf1a775f..f45d24f113 100644 --- a/package.json +++ b/package.json @@ -213,6 +213,7 @@ "qs": "^6.5.2", "rimraf": "^3.0.0", "sinon": "^7.4.2", + "stardust4ipfs": "^0.1.2", "stream-to-promise": "^2.2.0", "temp-write": "^4.0.0" }, diff --git a/src/core/runtime/libp2p-browser.js b/src/core/runtime/libp2p-browser.js index 70e1add67e..5e1348ecf4 100644 --- a/src/core/runtime/libp2p-browser.js +++ b/src/core/runtime/libp2p-browser.js @@ -9,7 +9,6 @@ const KadDHT = require('libp2p-kad-dht') const GossipSub = require('libp2p-gossipsub') const libp2p = require('libp2p') const mergeOptions = require('merge-options') -const multiaddr = require('multiaddr') class Node extends libp2p { constructor (_options) { @@ -26,8 +25,7 @@ class Node extends libp2p { modules: { transport: [ WS, - wrtcstar, - wsstar + wrtcstar ], streamMuxer: [ Multiplex diff --git a/test/core/libp2p.spec.js b/test/core/libp2p.spec.js index c470f79d83..1be590a54b 100644 --- a/test/core/libp2p.spec.js +++ b/test/core/libp2p.spec.js @@ -107,6 +107,31 @@ describe('libp2p customization', function () { done() }) }) + + it('should allow for custom overrideFunction', (done) => { + const ipfs = { + _repo: { + datastore + }, + _peerInfo: peerInfo, + _peerBook: peerBook, + // eslint-disable-next-line no-console + _print: console.log, + _options: { + libp2p: { + overrideFunction: require('stardust4ipfs') + } + } + } + + _libp2p = libp2pComponent(ipfs, testConfig) + + _libp2p.start((err) => { + expect(err).to.not.exist() + expect(_libp2p._transport).to.have.length(3) + done() + }) + }) }) describe('options', () => { @@ -149,13 +174,13 @@ describe('libp2p customization', function () { strictSigning: true } }) - expect(_libp2p._transport).to.have.length(3) + expect(_libp2p._transport).to.have.length(2) done() }) }) it('should allow for overriding via options', (done) => { - const wsstar = new WebSocketStar({ id: peerInfo.id }) + const wsstar = new Stardust({ id: peerInfo.id }) const ipfs = { _repo: { From 7783805c7c3d741287b1654ba72d9f32a5e1ab65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Fri, 1 Nov 2019 11:53:37 +0100 Subject: [PATCH 5/8] fix: add extend, fixes #2579 --- package.json | 2 +- src/core/components/libp2p.js | 11 +++++++++-- src/core/runtime/libp2p-browser.js | 5 ++++- src/core/runtime/libp2p-nodejs.js | 5 ++++- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index f45d24f113..2890d72233 100644 --- a/package.json +++ b/package.json @@ -213,7 +213,7 @@ "qs": "^6.5.2", "rimraf": "^3.0.0", "sinon": "^7.4.2", - "stardust4ipfs": "^0.1.2", + "stardust4ipfs": "^0.1.3", "stream-to-promise": "^2.2.0", "temp-write": "^4.0.0" }, diff --git a/src/core/components/libp2p.js b/src/core/components/libp2p.js index 5b4a47f84f..11e4761006 100644 --- a/src/core/components/libp2p.js +++ b/src/core/components/libp2p.js @@ -134,16 +134,23 @@ function defaultBundle ({ datastore, peerInfo, peerBook, options, config }) { } const libp2pUserOptions = get(options, 'libp2p', {}) + let libp2pExtend = get(options, 'libp2p.extend', false) let libp2pOptions = libp2pDefaults // allow user to specify overrideFunction, while at the same time allowing static arguments if (libp2pUserOptions.overrideFunction && typeof libp2pUserOptions.overrideFunction === 'function') { - libp2pOptions = mergeOptions(libp2pOptions, libp2pUserOptions.overrideFunction({ datastore, peerInfo, peerBook, options, config })) + const override = libp2pUserOptions.overrideFunction({ datastore, peerInfo, peerBook, options, config }) + + if (override.extend != null) { + libp2pExtend = override.extend + } + + libp2pOptions = mergeOptions.call({ concatArrays: libp2pExtend }, libp2pOptions, override) delete libp2pUserOptions.overrideFunction } - libp2pOptions = mergeOptions(libp2pOptions, libp2pUserOptions) + libp2pOptions = mergeOptions.call({ concatArrays: libp2pExtend }, libp2pOptions, libp2pUserOptions) // Required inline to reduce startup time // Note: libp2p-nodejs gets replaced by libp2p-browser when webpacked/browserified diff --git a/src/core/runtime/libp2p-browser.js b/src/core/runtime/libp2p-browser.js index 5e1348ecf4..5810afc96e 100644 --- a/src/core/runtime/libp2p-browser.js +++ b/src/core/runtime/libp2p-browser.js @@ -14,6 +14,9 @@ class Node extends libp2p { constructor (_options) { const wrtcstar = new WebRTCStar({ id: _options.peerInfo.id }) + const { extend } = _options + delete _options.extend + const defaults = { switch: { denyTTL: 2 * 60 * 1e3, // 2 minute base @@ -63,7 +66,7 @@ class Node extends libp2p { } } - super(mergeOptions(defaults, _options)) + super(mergeOptions.call({ concatArrays: extend }, defaults, _options)) } } diff --git a/src/core/runtime/libp2p-nodejs.js b/src/core/runtime/libp2p-nodejs.js index 6485e2d8d5..3ab22104ae 100644 --- a/src/core/runtime/libp2p-nodejs.js +++ b/src/core/runtime/libp2p-nodejs.js @@ -13,6 +13,9 @@ const mergeOptions = require('merge-options') class Node extends libp2p { constructor (_options) { + const { extend } = _options + delete _options.extend + const defaults = { switch: { denyTTL: 2 * 60 * 1e3, // 2 minute base @@ -66,7 +69,7 @@ class Node extends libp2p { } } - super(mergeOptions(defaults, _options)) + super(mergeOptions.call({ concatArrays: extend }, defaults, _options)) } } From 2e0217be2c48ab4ec70ef27af62831bc8dd9c738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Fri, 1 Nov 2019 12:04:08 +0100 Subject: [PATCH 6/8] chore: upgrade deps --- examples/exchange-files-in-browser/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/exchange-files-in-browser/package.json b/examples/exchange-files-in-browser/package.json index fff6b934cc..bec5c99a58 100644 --- a/examples/exchange-files-in-browser/package.json +++ b/examples/exchange-files-in-browser/package.json @@ -10,7 +10,7 @@ "devDependencies": { "browserify": "^16.2.3", "http-server": "~0.11.1", - "stardust4ipfs": "~0.1.1" + "stardust4ipfs": "~0.1.3" }, "dependencies": { "ipfs": "file:../../" From a333b96d7a30e61614fe4529f31eeb6b7fa42ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Fri, 1 Nov 2019 12:08:36 +0100 Subject: [PATCH 7/8] docs: add extend --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2a34d383b3..47b5b6f60b 100644 --- a/README.md +++ b/README.md @@ -540,6 +540,7 @@ You can see the bundle in action in the [custom libp2p example](examples/custom- - `overrideFunction` (object): - A function that allows overriding parts of libp2p's config, using dynamic arguments, without fully replacing the bundle as a custom libp2p bundle would do - It is called with the arguments `{ datastore, peerInfo, peerBook, options, config }` +- `extend` (boolean): Whether to fully replace the transport/discover arrays (`false`) or to concat them (`true`) - `modules` (object): - `transport` (Array<[libp2p.Transport](https://github.com/libp2p/interface-transport)>): An array of Libp2p transport classes/instances to use _instead_ of the defaults. See [libp2p/interface-transport](https://github.com/libp2p/interface-transport) for details. - `peerDiscovery` (Array<[libp2p.PeerDiscovery](https://github.com/libp2p/interface-peer-discovery)>): An array of Libp2p peer discovery classes/instances to use _instead_ of the defaults. See [libp2p/peer-discovery](https://github.com/libp2p/interface-peer-discovery) for details. If passing a class, configuration can be passed using the config section below under the key corresponding to you module's unique `tag` (a static property on the class) From 94a80556bdb9ef5479425595f686c16aab737296 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Tue, 5 Nov 2019 17:01:34 +0100 Subject: [PATCH 8/8] feat: use new bundle chaining ecosystem --- src/core/components/libp2p.js | 73 ++++++++++++++++++++++------------- test/core/libp2p.spec.js | 6 +-- 2 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/core/components/libp2p.js b/src/core/components/libp2p.js index 11e4761006..5f7b1d187f 100644 --- a/src/core/components/libp2p.js +++ b/src/core/components/libp2p.js @@ -8,20 +8,63 @@ const multiaddr = require('multiaddr') const DelegatedPeerRouter = require('libp2p-delegated-peer-routing') const DelegatedContentRouter = require('libp2p-delegated-content-routing') const PubsubRouters = require('../runtime/libp2p-pubsub-routers-nodejs') +const Libp2p = require('libp2p') module.exports = function libp2p (self, config) { const options = self._options || {} config = config || {} // Always create libp2p via a bundle function - const createBundle = typeof options.libp2p === 'function' + const createBundle = typeof options.libp2p !== 'undefined' ? (Array.isArray(options.libp2p) ? options.libp2p : [options.libp2p]) : [] + createBundle.unshift(defaultBundle) + + /* typeof options.libp2p === 'function' ? options.libp2p - : defaultBundle + : defaultBundle */ const { datastore } = self._repo const peerInfo = self._peerInfo const peerBook = self._peerInfoBook - const libp2p = createBundle({ options, config, datastore, peerInfo, peerBook }) + + const end = createBundle.length - 1 + let libp2p + let libp2pOpts + + options.libp2p = libp2pOpts = null + + createBundle.forEach((fncOrObj, i) => { + if (typeof fncOrObj === 'function') { + const r = fncOrObj({ options, config, datastore, peerInfo, peerBook }) + if (r instanceof Libp2p) { + if (i === end) { + libp2p = r + } else { + throw new Error('Using chained, but non-last function returned instance') + } + } else if (typeof r === 'object') { + if (r.extend) { + libp2pOpts = options.libp2p = mergeOptions.call({ concatArrays: true }, libp2pOpts, r) // extend + } else { + libp2pOpts = options.libp2p = r // override + } + } else if (typeof r === 'undefined') { + // ignore, go on + } else { + // maybe print a warning? + } + } else if (typeof fncOrObj === 'object') { + libp2pOpts = options.libp2p = mergeOptions.call({ concatArrays: fncOrObj.extend }, libp2pOpts, fncOrObj) + } else { + throw new TypeError('Option .libp2p has invalid type ' + typeof fncOrObj) + } + }) + + if (!libp2p) { + // Required inline to reduce startup time + // Note: libp2p-nodejs gets replaced by libp2p-browser when webpacked/browserified + const Node = require('../runtime/libp2p-nodejs') + libp2p = new Node(libp2pOpts) + } libp2p.on('stop', () => { // Clear our addresses so we can start clean @@ -133,27 +176,5 @@ function defaultBundle ({ datastore, peerInfo, peerBook, options, config }) { }) } - const libp2pUserOptions = get(options, 'libp2p', {}) - let libp2pExtend = get(options, 'libp2p.extend', false) - - let libp2pOptions = libp2pDefaults - - // allow user to specify overrideFunction, while at the same time allowing static arguments - if (libp2pUserOptions.overrideFunction && typeof libp2pUserOptions.overrideFunction === 'function') { - const override = libp2pUserOptions.overrideFunction({ datastore, peerInfo, peerBook, options, config }) - - if (override.extend != null) { - libp2pExtend = override.extend - } - - libp2pOptions = mergeOptions.call({ concatArrays: libp2pExtend }, libp2pOptions, override) - delete libp2pUserOptions.overrideFunction - } - - libp2pOptions = mergeOptions.call({ concatArrays: libp2pExtend }, libp2pOptions, libp2pUserOptions) - - // Required inline to reduce startup time - // Note: libp2p-nodejs gets replaced by libp2p-browser when webpacked/browserified - const Node = require('../runtime/libp2p-nodejs') - return new Node(libp2pOptions) + return libp2pDefaults } diff --git a/test/core/libp2p.spec.js b/test/core/libp2p.spec.js index 1be590a54b..b097da71d2 100644 --- a/test/core/libp2p.spec.js +++ b/test/core/libp2p.spec.js @@ -108,7 +108,7 @@ describe('libp2p customization', function () { }) }) - it('should allow for custom overrideFunction', (done) => { + it('should allow for custom bundle-chain', (done) => { const ipfs = { _repo: { datastore @@ -118,9 +118,7 @@ describe('libp2p customization', function () { // eslint-disable-next-line no-console _print: console.log, _options: { - libp2p: { - overrideFunction: require('stardust4ipfs') - } + libp2p: [require('stardust4ipfs')] } }