Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit 902e045

Browse files
vasco-santosAlan Shaw
authored and
Alan Shaw
committed
feat: gossipsub as default pubsub (#2298)
BREAKING CHANGE: The default pubsub implementation has changed from floodsub to [gossipsub](https://github.com/ChainSafe/gossipsub-js). Additionally, to enable pubsub programmatically set `pubsub.enabled: true` instead of `EXPERIMENTAL.pubsub: true` or via the CLI pass `--enable-pubsub` instead of `--enable-pubsub-experiment` to `jsipfs daemon`.
1 parent f6cf876 commit 902e045

26 files changed

+241
-77
lines changed

README.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ Configure remote preload nodes. The remote will preload content added on this no
324324
325325
| Type | Default |
326326
|------|---------|
327-
| object | `{ pubsub: false, ipnsPubsub: false, sharding: false }` |
327+
| object | `{ ipnsPubsub: false, sharding: false }` |
328328
329329
Enable and configure experimental features.
330330
@@ -495,6 +495,8 @@ You can see the bundle in action in the [custom libp2p example](examples/custom-
495495
- `modules` (object):
496496
- `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.
497497
- `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)
498+
- `dht` (object): a DHT implementation that enables PeerRouting and ContentRouting. Example [libp2p/js-libp2p-kad-dht](https://github.com/libp2p/js-libp2p-kad-dht)
499+
- `pubsub` (object): a Pubsub implementation on top of [libp2p/js-libp2p-pubsub](https://github.com/libp2p/js-libp2p-pubsub)
498500
- `config` (object):
499501
- `peerDiscovery` (object):
500502
- `autoDial` (boolean): Dial to discovered peers when under the Connection Manager min peer count watermark. (default `true`)
@@ -506,6 +508,11 @@ You can see the bundle in action in the [custom libp2p example](examples/custom-
506508
- `kBucketSize` (number): bucket size (default `20`)
507509
- `randomWalk` (object): configuration for random walk
508510
- `enabled` (boolean): whether random DHT walking is enabled (default `false`)
511+
- `pubsub` (object): Configuration options for Pubsub
512+
- `enabled` (boolean): if pubbsub subsystem should be enabled (default: `false`)
513+
- `emitSelf` (boolean): whether the node should emit to self on publish, in the event of the topic being subscribed (default: `true`)
514+
- `signMessages` (boolean): if messages should be signed (default: `true`)
515+
- `strictSigning` (boolean): if message signing should be required (default: `true`)
509516

510517
##### `options.connectionManager`
511518

doc/config.md

+12
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ The js-ipfs config file is a JSON document located in the root directory of the
1919
- [`PeerID`](#peerid)
2020
- [`PrivKey`](#privkey)
2121
- [`Keychain`](#keychain)
22+
- [`Pubsub`](#pubsub)
23+
- [`Router`](#router)
2224
- [`Swarm`](#swarm)
2325
- [`ConnMgr`](#connmgr)
2426

@@ -168,6 +170,16 @@ Default:
168170

169171
You can check the [parameter choice for pbkdf2](https://cryptosense.com/parameter-choice-for-pbkdf2/) for more information.
170172

173+
## `Pubsub`
174+
175+
Options for configuring the pubsub subsystem. It is important pointing out that this is not supported in the browser. If you want to configure a different pubsub router in the browser you must configure `libp2p.modules.pubsub` options instead.
176+
177+
### `Router`
178+
179+
A string value for specifying which pubsub routing protocol to use. You can either use `gossipsub` in order to use the [ChainSafe/gossipsub-js](https://github.com/ChainSafe/gossipsub-js) implementation, or `floodsub` to use the [libp2p/js-libp2p-floodsub](https://github.com/libp2p/js-libp2p-floodsub) implementation. You can read more about these implementations on the [libp2p/specs/pubsub](https://github.com/libp2p/specs/tree/master/pubsub) document.
180+
181+
Default: `gossipsub`
182+
171183
## `Swarm`
172184

173185
Options for configuring the swarm.

examples/circuit-relaying/src/app.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ document.addEventListener('DOMContentLoaded', async () => {
3636
enabled: true // make this node a relay (HOP)
3737
}
3838
},
39-
EXPERIMENTAL: {
40-
pubsub: true // enable pubsub
39+
pubsub: {
40+
enabled: true
4141
},
4242
config: {
4343
Bootstrap: []

examples/custom-libp2p/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,8 @@ const libp2pBundle = (opts) => {
9696
timeout: 2e3 // End the query quickly since we're running so frequently
9797
}
9898
},
99-
EXPERIMENTAL: {
100-
pubsub: true
99+
pubsub: {
100+
enabled: true
101101
}
102102
}
103103
})

examples/custom-libp2p/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"license": "MIT",
1111
"dependencies": {
1212
"ipfs": "file:../../",
13-
"libp2p": "~0.25.0",
13+
"libp2p": "~0.26.1",
1414
"libp2p-bootstrap": "~0.9.7",
1515
"libp2p-kad-dht": "~0.15.0",
1616
"libp2p-mdns": "~0.12.2",

examples/exchange-files-in-browser/public/app.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ let info
4444
async function start () {
4545
if (!node) {
4646
const options = {
47-
EXPERIMENTAL: {
48-
pubsub: true
47+
pubsub: {
48+
enabled: true
4949
},
5050
repo: 'ipfs-' + Math.random(),
5151
config: {

package.json

+7-4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"./src/core/runtime/dns-nodejs.js": "./src/core/runtime/dns-browser.js",
2222
"./src/core/runtime/fetch-nodejs.js": "./src/core/runtime/fetch-browser.js",
2323
"./src/core/runtime/libp2p-nodejs.js": "./src/core/runtime/libp2p-browser.js",
24+
"./src/core/runtime/libp2p-pubsub-routers-nodejs.js": "./src/core/runtime/libp2p-pubsub-routers-browser.js",
2425
"./src/core/runtime/preload-nodejs.js": "./src/core/runtime/preload-browser.js",
2526
"./src/core/runtime/repo-nodejs.js": "./src/core/runtime/repo-browser.js",
2627
"./src/core/runtime/ipld-nodejs.js": "./src/core/runtime/ipld-browser.js",
@@ -96,7 +97,7 @@
9697
"ipfs-bitswap": "~0.25.1",
9798
"ipfs-block": "~0.8.1",
9899
"ipfs-block-service": "~0.15.2",
99-
"ipfs-http-client": "^33.1.1",
100+
"ipfs-http-client": "^34.0.0",
100101
"ipfs-http-response": "~0.3.1",
101102
"ipfs-mfs": "~0.12.0",
102103
"ipfs-multipart": "~0.1.1",
@@ -121,11 +122,13 @@
121122
"iso-url": "~0.4.6",
122123
"just-safe-set": "^2.1.0",
123124
"kind-of": "^6.0.2",
124-
"libp2p": "~0.25.4",
125+
"libp2p": "~0.26.1",
125126
"libp2p-bootstrap": "~0.9.3",
126127
"libp2p-crypto": "~0.16.0",
127128
"libp2p-delegated-content-routing": "^0.2.4",
128129
"libp2p-delegated-peer-routing": "^0.2.4",
130+
"libp2p-floodsub": "^0.17.0",
131+
"libp2p-gossipsub": "~0.0.4",
129132
"libp2p-kad-dht": "~0.15.3",
130133
"libp2p-keychain": "~0.4.2",
131134
"libp2p-mdns": "~0.12.0",
@@ -191,8 +194,8 @@
191194
"execa": "^2.0.4",
192195
"form-data": "^2.5.1",
193196
"hat": "0.0.3",
194-
"interface-ipfs-core": "^0.110.0",
195-
"ipfsd-ctl": "^0.44.1",
197+
"interface-ipfs-core": "^0.111.0",
198+
"ipfsd-ctl": "~0.45.0",
196199
"libp2p-websocket-star": "~0.10.2",
197200
"ncp": "^2.0.0",
198201
"p-event": "^4.1.0",

src/cli/commands/daemon.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ module.exports = {
1616
type: 'boolean',
1717
default: false
1818
})
19-
.option('enable-pubsub-experiment', {
19+
.option('enable-pubsub', {
20+
alias: 'enable-pubsub-experiment',
2021
type: 'boolean',
2122
default: false
2223
})
@@ -53,8 +54,8 @@ module.exports = {
5354
offline: argv.offline,
5455
pass: argv.pass,
5556
preload: { enabled: argv.enablePreload },
57+
pubsub: { enabled: argv.enablePubsub },
5658
EXPERIMENTAL: {
57-
pubsub: argv.enablePubsubExperiment,
5859
ipnsPubsub: argv.enableNamesysPubsub,
5960
dht: argv.enableDhtExperiment,
6061
sharding: argv.enableShardingExperiment

src/cli/daemon.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class Daemon {
3030
async start () {
3131
this._log('starting')
3232

33-
const libp2p = { modules: {} }
33+
const libp2p = { modules: {}, config: {} }
3434

3535
// Attempt to use any of the WebRTC versions available globally
3636
let electronWebRTC

src/cli/utils.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ exports.getIPFS = (argv, callback) => {
5050
init: false,
5151
start: false,
5252
pass: argv.pass,
53-
EXPERIMENTAL: {
54-
pubsub: true
53+
pubsub: {
54+
enabled: true
5555
}
5656
})
5757

src/core/components/libp2p.js

+16-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
const get = require('dlv')
44
const mergeOptions = require('merge-options')
5+
const errCode = require('err-code')
56
const ipnsUtils = require('../ipns/routing/utils')
67
const multiaddr = require('multiaddr')
78
const DelegatedPeerRouter = require('libp2p-delegated-peer-routing')
89
const DelegatedContentRouter = require('libp2p-delegated-content-routing')
10+
const PubsubRouters = require('../runtime/libp2p-pubsub-routers-nodejs')
911

1012
module.exports = function libp2p (self, config) {
1113
const options = self._options || {}
@@ -58,13 +60,24 @@ function defaultBundle ({ datastore, peerInfo, peerBook, options, config }) {
5860
peerRouting = [new DelegatedPeerRouter(delegatedApiOptions)]
5961
}
6062

63+
const getPubsubRouter = () => {
64+
const router = get(config, 'Pubsub.Router', 'gossipsub')
65+
66+
if (!PubsubRouters[router]) {
67+
throw errCode(new Error(`Router unavailable. Configure libp2p.modules.pubsub to use the ${router} router.`), 'ERR_NOT_SUPPORTED')
68+
}
69+
70+
return PubsubRouters[router]
71+
}
72+
6173
const libp2pDefaults = {
6274
datastore,
6375
peerInfo,
6476
peerBook,
6577
modules: {
6678
contentRouting,
67-
peerRouting
79+
peerRouting,
80+
pubsub: getPubsubRouter()
6881
},
6982
config: {
7083
peerDiscovery: {
@@ -105,8 +118,8 @@ function defaultBundle ({ datastore, peerInfo, peerBook, options, config }) {
105118
ipns: ipnsUtils.selector
106119
}
107120
},
108-
EXPERIMENTAL: {
109-
pubsub: get(options, 'EXPERIMENTAL.pubsub', false)
121+
pubsub: {
122+
enabled: get(options, 'pubsub.enabled', false)
110123
}
111124
},
112125
connectionManager: get(options, 'connectionManager',

src/core/components/pubsub.js

+10-19
Original file line numberDiff line numberDiff line change
@@ -16,65 +16,56 @@ module.exports = function pubsub (self) {
1616
options = {}
1717
}
1818

19-
if (!self._options.EXPERIMENTAL.pubsub) {
19+
if (!self.libp2p.pubsub) {
2020
return callback
2121
? setImmediate(() => callback(errPubsubDisabled()))
2222
: Promise.reject(errPubsubDisabled())
2323
}
2424

2525
if (!callback) {
26-
return new Promise((resolve, reject) => {
27-
self.libp2p.pubsub.subscribe(topic, options, handler, (err) => {
28-
if (err) {
29-
return reject(err)
30-
}
31-
resolve()
32-
})
33-
})
26+
return self.libp2p.pubsub.subscribe(topic, handler, options)
3427
}
3528

36-
self.libp2p.pubsub.subscribe(topic, options, handler, callback)
29+
self.libp2p.pubsub.subscribe(topic, handler, options, callback)
3730
},
3831

3932
unsubscribe: (topic, handler, callback) => {
40-
if (!self._options.EXPERIMENTAL.pubsub) {
33+
if (!self.libp2p.pubsub) {
4134
return callback
4235
? setImmediate(() => callback(errPubsubDisabled()))
4336
: Promise.reject(errPubsubDisabled())
4437
}
4538

46-
self.libp2p.pubsub.unsubscribe(topic, handler)
47-
4839
if (!callback) {
49-
return Promise.resolve()
40+
return self.libp2p.pubsub.unsubscribe(topic, handler)
5041
}
5142

52-
setImmediate(() => callback())
43+
self.libp2p.pubsub.unsubscribe(topic, handler, callback)
5344
},
5445

5546
publish: promisify((topic, data, callback) => {
56-
if (!self._options.EXPERIMENTAL.pubsub) {
47+
if (!self.libp2p.pubsub) {
5748
return setImmediate(() => callback(errPubsubDisabled()))
5849
}
5950
self.libp2p.pubsub.publish(topic, data, callback)
6051
}),
6152

6253
ls: promisify((callback) => {
63-
if (!self._options.EXPERIMENTAL.pubsub) {
54+
if (!self.libp2p.pubsub) {
6455
return setImmediate(() => callback(errPubsubDisabled()))
6556
}
6657
self.libp2p.pubsub.ls(callback)
6758
}),
6859

6960
peers: promisify((topic, callback) => {
70-
if (!self._options.EXPERIMENTAL.pubsub) {
61+
if (!self.libp2p.pubsub) {
7162
return setImmediate(() => callback(errPubsubDisabled()))
7263
}
7364
self.libp2p.pubsub.peers(topic, callback)
7465
}),
7566

7667
setMaxListeners (n) {
77-
if (!self._options.EXPERIMENTAL.pubsub) {
68+
if (!self.libp2p.pubsub) {
7869
throw errPubsubDisabled()
7970
}
8071
self.libp2p.pubsub.setMaxListeners(n)

src/core/config.js

+6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ const configSchema = s({
3232
addresses: optional(s(['multiaddr'])),
3333
interval: 'number?'
3434
}, { enabled: true, interval: 30 * 1000 }),
35+
pubsub: optional(s({
36+
enabled: 'boolean?'
37+
})),
3538
init: optional(union(['boolean', s({
3639
bits: 'number?',
3740
emptyRepo: 'boolean?',
@@ -68,6 +71,9 @@ const configSchema = s({
6871
}))
6972
})),
7073
Bootstrap: optional(s(['multiaddr-ipfs'])),
74+
Pubsub: optional(s({
75+
Router: 'string?'
76+
})),
7177
Swarm: optional(s({
7278
ConnMgr: optional(s({
7379
LowWater: 'number?',

src/core/index.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const multihashing = require('multihashing-async')
1515
const CID = require('cids')
1616
const debug = require('debug')
1717
const mergeOptions = require('merge-options')
18+
const get = require('dlv')
1819
const EventEmitter = require('events')
1920

2021
const config = require('./config')
@@ -46,6 +47,9 @@ class IPFS extends EventEmitter {
4647
init: true,
4748
start: true,
4849
EXPERIMENTAL: {},
50+
pubsub: {
51+
enabled: false
52+
},
4953
preload: {
5054
enabled: true,
5155
addresses: [
@@ -131,13 +135,14 @@ class IPFS extends EventEmitter {
131135
this.stats = components.stats(this)
132136
this.resolve = components.resolve(this)
133137

134-
if (this._options.EXPERIMENTAL.pubsub) {
135-
this.log('EXPERIMENTAL pubsub is enabled')
138+
if (this._options.pubsub.enabled) {
139+
this.log('pubsub is enabled')
136140
}
137141
if (this._options.EXPERIMENTAL.ipnsPubsub) {
138-
if (!this._options.EXPERIMENTAL.pubsub) {
139-
this.log('EXPERIMENTAL pubsub is enabled to use IPNS pubsub')
140-
this._options.EXPERIMENTAL.pubsub = true
142+
// if (!this._options.pubsub.enabled) {
143+
if (!get(this._options, 'pubsub.enabled', false)) {
144+
this.log('pubsub is enabled to use EXPERIMENTAL IPNS pubsub')
145+
this._options.pubsub.enabled = true
141146
}
142147

143148
this.log('EXPERIMENTAL IPNS pubsub is enabled')

src/core/runtime/config-nodejs.js

+3
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ module.exports = () => ({
4040
'/dns4/node0.preload.ipfs.io/tcp/443/wss/ipfs/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic',
4141
'/dns4/node1.preload.ipfs.io/tcp/443/wss/ipfs/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6'
4242
],
43+
Pubsub: {
44+
Router: 'gossipsub'
45+
},
4346
Swarm: {
4447
ConnMgr: {
4548
LowWater: 200,

0 commit comments

Comments
 (0)