refactor: pubsub subsystem

This commit is contained in:
Vasco Santos
2019-10-22 14:11:51 +02:00
parent 751bc00f1b
commit dcd127b7a5
9 changed files with 457 additions and 131 deletions

View File

@ -211,22 +211,18 @@ class Node extends Libp2p {
**IMPORTANT NOTE**: All the methods listed in the API section that take a callback are also now Promisified. Libp2p is migrating away from callbacks to async/await, and in a future release (that will be announced in advance), callback support will be removed entirely. You can follow progress of the async/await endeavor at https://github.com/ipfs/js-ipfs/issues/1670. **IMPORTANT NOTE**: All the methods listed in the API section that take a callback are also now Promisified. Libp2p is migrating away from callbacks to async/await, and in a future release (that will be announced in advance), callback support will be removed entirely. You can follow progress of the async/await endeavor at https://github.com/ipfs/js-ipfs/issues/1670.
#### Create a Node - `Libp2p.createLibp2p(options, callback)` #### Create a Node - `Libp2p.create(options)`
> Behaves exactly like `new Libp2p(options)`, but doesn't require a PeerInfo. One will be generated instead > Behaves exactly like `new Libp2p(options)`, but doesn't require a PeerInfo. One will be generated instead
```js ```js
const { createLibp2p } = require('libp2p') const { create } = require('libp2p')
createLibp2p(options, (err, libp2p) => { const libp2p = await create(options)
if (err) throw err
libp2p.start((err) => { await libp2p.start()
if (err) throw err
})
})
``` ```
- `options`: Object of libp2p configuration options - `options`: Object of libp2p configuration options
- `callback`: Function with signature `function (Error, Libp2p) {}`
#### Create a Node alternative - `new Libp2p(options)` #### Create a Node alternative - `new Libp2p(options)`

View File

@ -62,6 +62,7 @@
"multiaddr": "^7.1.0", "multiaddr": "^7.1.0",
"multistream-select": "^0.15.0", "multistream-select": "^0.15.0",
"once": "^1.4.0", "once": "^1.4.0",
"p-map": "^3.0.0",
"p-queue": "^6.1.1", "p-queue": "^6.1.1",
"p-settle": "^3.1.0", "p-settle": "^3.1.0",
"peer-id": "^0.13.3", "peer-id": "^0.13.3",
@ -90,8 +91,8 @@
"libp2p-bootstrap": "^0.9.7", "libp2p-bootstrap": "^0.9.7",
"libp2p-delegated-content-routing": "^0.2.2", "libp2p-delegated-content-routing": "^0.2.2",
"libp2p-delegated-peer-routing": "^0.2.2", "libp2p-delegated-peer-routing": "^0.2.2",
"libp2p-floodsub": "~0.17.0", "libp2p-floodsub": "libp2p/js-libp2p-floodsub#refactor/async",
"libp2p-gossipsub": "~0.0.4", "libp2p-gossipsub": "ChainSafe/gossipsub-js#refactor/async",
"libp2p-kad-dht": "^0.15.3", "libp2p-kad-dht": "^0.15.3",
"libp2p-mdns": "^0.12.3", "libp2p-mdns": "^0.12.3",
"libp2p-mplex": "^0.9.1", "libp2p-mplex": "^0.9.1",
@ -103,6 +104,7 @@
"lodash.times": "^4.3.2", "lodash.times": "^4.3.2",
"nock": "^10.0.6", "nock": "^10.0.6",
"p-defer": "^3.0.0", "p-defer": "^3.0.0",
"p-wait-for": "^3.1.0",
"portfinder": "^1.0.20", "portfinder": "^1.0.20",
"pull-goodbye": "0.0.2", "pull-goodbye": "0.0.2",
"pull-length-prefixed": "^1.3.3", "pull-length-prefixed": "^1.3.3",

View File

@ -1,7 +1,7 @@
'use strict' 'use strict'
const FSM = require('fsm-event') const FSM = require('fsm-event')
const EventEmitter = require('events').EventEmitter const { EventEmitter } = require('events')
const debug = require('debug') const debug = require('debug')
const log = debug('libp2p') const log = debug('libp2p')
log.error = debug('libp2p:error') log.error = debug('libp2p:error')
@ -9,7 +9,6 @@ const errCode = require('err-code')
const promisify = require('promisify-es6') const promisify = require('promisify-es6')
const each = require('async/each') const each = require('async/each')
const nextTick = require('async/nextTick')
const PeerInfo = require('peer-info') const PeerInfo = require('peer-info')
const multiaddr = require('multiaddr') const multiaddr = require('multiaddr')
@ -66,6 +65,8 @@ class Libp2p extends EventEmitter {
this._transport = [] // Transport instances/references this._transport = [] // Transport instances/references
this._discovery = [] // Discovery service instances/references this._discovery = [] // Discovery service instances/references
this.peerStore = new PeerStore()
// create the switch, and listen for errors // create the switch, and listen for errors
this._switch = new Switch(this.peerInfo, this.peerStore, this._options.switch) this._switch = new Switch(this.peerInfo, this.peerStore, this._options.switch)
@ -147,7 +148,7 @@ class Libp2p extends EventEmitter {
} }
// start pubsub // start pubsub
if (this._modules.pubsub && this._config.pubsub.enabled !== false) { if (this._modules.pubsub) {
this.pubsub = pubsub(this, this._modules.pubsub, this._config.pubsub) this.pubsub = pubsub(this, this._modules.pubsub, this._config.pubsub)
} }
@ -251,6 +252,7 @@ class Libp2p extends EventEmitter {
this.state('stop') this.state('stop')
try { try {
this.pubsub && await this.pubsub.stop()
await this.transportManager.close() await this.transportManager.close()
await this._switch.stop() await this._switch.stop()
} catch (err) { } catch (err) {
@ -385,10 +387,16 @@ class Libp2p extends EventEmitter {
const multiaddrs = this.peerInfo.multiaddrs.toArray() const multiaddrs = this.peerInfo.multiaddrs.toArray()
// Start parallel tasks // Start parallel tasks
const tasks = [
this.transportManager.listen(multiaddrs)
]
if (this._config.pubsub.enabled) {
this.pubsub && this.pubsub.start()
}
try { try {
await Promise.all([ await Promise.all(tasks)
this.transportManager.listen(multiaddrs)
])
} catch (err) { } catch (err) {
log.error(err) log.error(err)
this.emit('error', err) this.emit('error', err)
@ -483,16 +491,15 @@ module.exports = Libp2p
* Like `new Libp2p(options)` except it will create a `PeerInfo` * Like `new Libp2p(options)` except it will create a `PeerInfo`
* instance if one is not provided in options. * instance if one is not provided in options.
* @param {object} options Libp2p configuration options * @param {object} options Libp2p configuration options
* @param {function(Error, Libp2p)} callback * @returns {Libp2p}
* @returns {void}
*/ */
module.exports.createLibp2p = promisify((options, callback) => { module.exports.create = async (options = {}) => {
if (options.peerInfo) { if (options.peerInfo) {
return nextTick(callback, null, new Libp2p(options)) return new Libp2p(options)
} }
PeerInfo.create((err, peerInfo) => {
if (err) return callback(err) const peerInfo = await PeerInfo.create()
options.peerInfo = peerInfo
callback(null, new Libp2p(options)) options.peerInfo = peerInfo
}) return new Libp2p(options)
}) }

View File

@ -1,52 +1,21 @@
'use strict' 'use strict'
const nextTick = require('async/nextTick')
const { messages, codes } = require('./errors')
const promisify = require('promisify-es6')
const errCode = require('err-code') const errCode = require('err-code')
const { messages, codes } = require('./errors')
module.exports = (node, Pubsub, config) => { module.exports = (node, Pubsub, config) => {
const pubsub = new Pubsub(node, config) const pubsub = new Pubsub(node.peerInfo, node.registrar, config)
return { return {
/** /**
* Subscribe the given handler to a pubsub topic * Subscribe the given handler to a pubsub topic
*
* @param {string} topic * @param {string} topic
* @param {function} handler The handler to subscribe * @param {function} handler The handler to subscribe
* @param {object|null} [options] * @returns {void}
* @param {function} [callback] An optional callback
*
* @returns {Promise|void} A promise is returned if no callback is provided
*
* @example <caption>Subscribe a handler to a topic</caption>
*
* // `null` must be passed for options until subscribe is no longer using promisify
* const handler = (message) => { }
* await libp2p.subscribe(topic, handler, null)
*
* @example <caption>Use a callback instead of the Promise api</caption>
*
* // `options` may be passed or omitted when supplying a callback
* const handler = (message) => { }
* libp2p.subscribe(topic, handler, callback)
*/ */
subscribe: (topic, handler, options, callback) => { subscribe: (topic, handler) => {
// can't use promisify because it thinks the handler is a callback
if (typeof options === 'function') {
callback = options
options = {}
}
if (!node.isStarted() && !pubsub.started) { if (!node.isStarted() && !pubsub.started) {
const err = errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED) throw errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)
if (callback) {
return nextTick(() => callback(err))
}
return Promise.reject(err)
} }
if (pubsub.listenerCount(topic) === 0) { if (pubsub.listenerCount(topic) === 0) {
@ -54,46 +23,16 @@ module.exports = (node, Pubsub, config) => {
} }
pubsub.on(topic, handler) pubsub.on(topic, handler)
if (callback) {
return nextTick(() => callback())
}
return Promise.resolve()
}, },
/** /**
* Unsubscribes from a pubsub topic * Unsubscribes from a pubsub topic
*
* @param {string} topic * @param {string} topic
* @param {function|null} handler The handler to unsubscribe from * @param {function} [handler] The handler to unsubscribe from
* @param {function} [callback] An optional callback
*
* @returns {Promise|void} A promise is returned if no callback is provided
*
* @example <caption>Unsubscribe a topic for all handlers</caption>
*
* // `null` must be passed until unsubscribe is no longer using promisify
* await libp2p.unsubscribe(topic, null)
*
* @example <caption>Unsubscribe a topic for 1 handler</caption>
*
* await libp2p.unsubscribe(topic, handler)
*
* @example <caption>Use a callback instead of the Promise api</caption>
*
* libp2p.unsubscribe(topic, handler, callback)
*/ */
unsubscribe: (topic, handler, callback) => { unsubscribe: (topic, handler) => {
// can't use promisify because it thinks the handler is a callback
if (!node.isStarted() && !pubsub.started) { if (!node.isStarted() && !pubsub.started) {
const err = errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED) throw errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)
if (callback) {
return nextTick(() => callback(err))
}
return Promise.reject(err)
} }
if (!handler) { if (!handler) {
@ -105,61 +44,46 @@ module.exports = (node, Pubsub, config) => {
if (pubsub.listenerCount(topic) === 0) { if (pubsub.listenerCount(topic) === 0) {
pubsub.unsubscribe(topic) pubsub.unsubscribe(topic)
} }
if (callback) {
return nextTick(() => callback())
}
return Promise.resolve()
}, },
publish: promisify((topic, data, callback) => { publish: (topic, data) => {
if (!node.isStarted() && !pubsub.started) { if (!node.isStarted() && !pubsub.started) {
return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)) throw errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)
} }
try { try {
data = Buffer.from(data) data = Buffer.from(data)
} catch (err) { } catch (err) {
return nextTick(callback, errCode(new Error('data must be convertible to a Buffer'), 'ERR_DATA_IS_NOT_VALID')) throw errCode(new Error('data must be convertible to a Buffer'), 'ERR_DATA_IS_NOT_VALID')
} }
pubsub.publish(topic, data, callback) return pubsub.publish(topic, data)
}), },
ls: promisify((callback) => { getTopics: () => {
if (!node.isStarted() && !pubsub.started) { if (!node.isStarted() && !pubsub.started) {
return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)) throw errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)
} }
const subscriptions = Array.from(pubsub.subscriptions) return pubsub.getTopics()
},
nextTick(() => callback(null, subscriptions)) getPeersSubscribed: (topic) => {
}),
peers: promisify((topic, callback) => {
if (!node.isStarted() && !pubsub.started) { if (!node.isStarted() && !pubsub.started) {
return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)) throw errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)
} }
if (typeof topic === 'function') { return pubsub.getPeersSubscribed(topic)
callback = topic },
topic = null
}
const peers = Array.from(pubsub.peers.values())
.filter((peer) => topic ? peer.topics.has(topic) : true)
.map((peer) => peer.info.id.toB58String())
nextTick(() => callback(null, peers))
}),
setMaxListeners (n) { setMaxListeners (n) {
return pubsub.setMaxListeners(n) return pubsub.setMaxListeners(n)
}, },
start: promisify((cb) => pubsub.start(cb)), _pubsub: pubsub,
stop: promisify((cb) => pubsub.stop(cb)) start: () => pubsub.start(),
stop: () => pubsub.stop()
} }
} }

View File

@ -186,7 +186,7 @@ class Upgrader {
const { stream, protocol } = await mss.handle(Array.from(this.protocols.keys())) const { stream, protocol } = await mss.handle(Array.from(this.protocols.keys()))
log('%s: incoming stream opened on %s', direction, protocol) log('%s: incoming stream opened on %s', direction, protocol)
connection.addStream(stream, protocol) connection.addStream(stream, protocol)
this._onStream({ connection, stream, protocol }) this._onStream({ connection, stream, protocol, remotePeer })
} catch (err) { } catch (err) {
log.error(err) log.error(err)
} }
@ -254,9 +254,9 @@ class Upgrader {
* @param {Stream} options.stream * @param {Stream} options.stream
* @param {string} options.protocol * @param {string} options.protocol
*/ */
_onStream ({ connection, stream, protocol }) { _onStream ({ connection, stream, protocol, remotePeer }) {
const handler = this.protocols.get(protocol) const handler = this.protocols.get(protocol)
handler({ connection, stream, protocol }) handler({ connection, stream, protocol, remotePeer })
} }
/** /**

View File

@ -0,0 +1,93 @@
'use strict'
/* eslint-env mocha */
const chai = require('chai')
chai.use(require('dirty-chai'))
const { expect } = chai
const mergeOptions = require('merge-options')
const multiaddr = require('multiaddr')
const PeerInfo = require('peer-info')
const { create } = require('../../src')
const { baseOptions, subsystemOptions } = require('./utils')
const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0')
describe('Pubsub subsystem is configurable', () => {
let libp2p
afterEach(async () => {
libp2p && await libp2p.stop()
})
it('should not exist if no module is provided', async () => {
libp2p = await create(baseOptions)
expect(libp2p.pubsub).to.not.exist()
})
it('should exist if the module is provided', async () => {
libp2p = await create(subsystemOptions)
expect(libp2p.pubsub).to.exist()
})
it('should start and stop by default once libp2p starts', async () => {
const peerInfo = await PeerInfo.create()
peerInfo.multiaddrs.add(listenAddr)
const customOptions = mergeOptions(subsystemOptions, {
peerInfo
})
libp2p = await create(customOptions)
expect(libp2p.pubsub._pubsub.started).to.equal(false)
await libp2p.start()
expect(libp2p.pubsub._pubsub.started).to.equal(true)
await libp2p.stop()
expect(libp2p.pubsub._pubsub.started).to.equal(false)
})
it('should not start if disabled once libp2p starts', async () => {
const peerInfo = await PeerInfo.create()
peerInfo.multiaddrs.add(listenAddr)
const customOptions = mergeOptions(subsystemOptions, {
peerInfo,
config: {
pubsub: {
enabled: false
}
}
})
libp2p = await create(customOptions)
expect(libp2p.pubsub._pubsub.started).to.equal(false)
await libp2p.start()
expect(libp2p.pubsub._pubsub.started).to.equal(false)
})
it('should allow a manual start', async () => {
const peerInfo = await PeerInfo.create()
peerInfo.multiaddrs.add(listenAddr)
const customOptions = mergeOptions(subsystemOptions, {
peerInfo,
config: {
pubsub: {
enabled: false
}
}
})
libp2p = await create(customOptions)
await libp2p.start()
expect(libp2p.pubsub._pubsub.started).to.equal(false)
await libp2p.pubsub.start()
expect(libp2p.pubsub._pubsub.started).to.equal(true)
})
})

View File

@ -0,0 +1,101 @@
'use strict'
/* eslint-env mocha */
const chai = require('chai')
chai.use(require('dirty-chai'))
const { expect } = chai
const pWaitFor = require('p-wait-for')
const pDefer = require('p-defer')
const mergeOptions = require('merge-options')
const Floodsub = require('libp2p-floodsub')
const Gossipsub = require('libp2p-gossipsub')
const { multicodec: floodsubMulticodec } = require('libp2p-floodsub')
const { multicodec: gossipsubMulticodec } = require('libp2p-gossipsub')
const multiaddr = require('multiaddr')
const PeerInfo = require('peer-info')
const { create } = require('../../src')
const { baseOptions } = require('./utils')
const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0')
const remoteListenAddr = multiaddr('/ip4/127.0.0.1/tcp/0')
describe('Pubsub subsystem is able to use different implementations', () => {
let peerInfo, remotePeerInfo
let libp2p, remoteLibp2p
let remAddr
beforeEach(async () => {
[peerInfo, remotePeerInfo] = await Promise.all([
PeerInfo.create(),
PeerInfo.create()
])
peerInfo.multiaddrs.add(listenAddr)
remotePeerInfo.multiaddrs.add(remoteListenAddr)
})
afterEach(() => Promise.all([
libp2p && libp2p.stop(),
remoteLibp2p && remoteLibp2p.stop()
]))
it('Floodsub nodes', () => {
return pubsubTest(floodsubMulticodec, Floodsub)
})
it('Gossipsub nodes', () => {
return pubsubTest(gossipsubMulticodec, Gossipsub)
})
const pubsubTest = async (multicodec, pubsub) => {
const defer = pDefer()
const topic = 'test-topic'
const data = 'hey!'
libp2p = await create(mergeOptions(baseOptions, {
peerInfo,
modules: {
pubsub: pubsub
}
}))
remoteLibp2p = await create(mergeOptions(baseOptions, {
peerInfo: remotePeerInfo,
modules: {
pubsub: pubsub
}
}))
await Promise.all([
libp2p.start(),
remoteLibp2p.start()
])
const libp2pId = libp2p.peerInfo.id.toB58String()
remAddr = remoteLibp2p.transportManager.getAddrs()[0]
const connection = await libp2p.dialProtocol(remAddr, multicodec)
await new Promise((resolve) => setTimeout(resolve, 1000))
expect(connection).to.exist()
libp2p.pubsub.subscribe(topic, (msg) => {
expect(msg.data.toString()).to.equal(data)
defer.resolve()
})
// wait for remoteLibp2p to know about libp2p subscription
await pWaitFor(() => {
const subscribedPeers = remoteLibp2p.pubsub.getPeersSubscribed(topic)
return subscribedPeers.includes(libp2pId)
})
await new Promise((resolve) => setTimeout(resolve, 1000))
remoteLibp2p.pubsub.publish(topic, data)
await defer.promise
}
})

View File

@ -0,0 +1,174 @@
'use strict'
/* eslint-env mocha */
const chai = require('chai')
chai.use(require('dirty-chai'))
const { expect } = chai
const sinon = require('sinon')
const pWaitFor = require('p-wait-for')
const pDefer = require('p-defer')
const mergeOptions = require('merge-options')
const multiaddr = require('multiaddr')
const PeerInfo = require('peer-info')
const { create } = require('../../src')
const { subsystemOptions, subsystemMulticodecs } = require('./utils')
const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0')
const remoteListenAddr = multiaddr('/ip4/127.0.0.1/tcp/0')
describe('Pubsub subsystem operates correctly', () => {
let peerInfo, remotePeerInfo
let libp2p, remoteLibp2p
let remAddr
beforeEach(async () => {
[peerInfo, remotePeerInfo] = await Promise.all([
PeerInfo.create(),
PeerInfo.create()
])
peerInfo.multiaddrs.add(listenAddr)
remotePeerInfo.multiaddrs.add(remoteListenAddr)
})
describe('pubsub started before connect', () => {
beforeEach(async () => {
libp2p = await create(mergeOptions(subsystemOptions, {
peerInfo
}))
remoteLibp2p = await create(mergeOptions(subsystemOptions, {
peerInfo: remotePeerInfo
}))
await libp2p.start()
await remoteLibp2p.start()
remAddr = remoteLibp2p.transportManager.getAddrs()[0]
})
afterEach(() => Promise.all([
libp2p && libp2p.stop(),
remoteLibp2p && remoteLibp2p.stop()
]))
afterEach(() => {
sinon.restore()
})
it('should get notified of connected peers on dial', async () => {
sinon.spy(libp2p.registrar, 'onConnect')
sinon.spy(remoteLibp2p.registrar, 'onConnect')
const connection = await libp2p.dialProtocol(remAddr, subsystemMulticodecs)
expect(connection).to.exist()
expect(libp2p.pubsub._pubsub.peers.size).to.be.eql(1)
expect(remoteLibp2p.pubsub._pubsub.peers.size).to.be.eql(1)
expect(libp2p.registrar.onConnect.callCount).to.equal(1)
expect(remoteLibp2p.registrar.onConnect.callCount).to.equal(1)
})
it('should receive pubsub messages', async () => {
const defer = pDefer()
const topic = 'test-topic'
const data = 'hey!'
const libp2pId = libp2p.peerInfo.id.toB58String()
await libp2p.dialProtocol(remAddr, subsystemMulticodecs)
let subscribedTopics = libp2p.pubsub.getTopics()
expect(subscribedTopics).to.not.include(topic)
libp2p.pubsub.subscribe(topic, (msg) => {
expect(msg.data.toString()).to.equal(data)
defer.resolve()
})
subscribedTopics = libp2p.pubsub.getTopics()
expect(subscribedTopics).to.include(topic)
// wait for remoteLibp2p to know about libp2p subscription
await pWaitFor(() => {
const subscribedPeers = remoteLibp2p.pubsub.getPeersSubscribed(topic)
return subscribedPeers.includes(libp2pId)
})
remoteLibp2p.pubsub.publish(topic, data)
await defer.promise
})
})
// TODO: Needs identify push
describe.skip('pubsub started after connect', () => {
beforeEach(async () => {
libp2p = await create(mergeOptions(subsystemOptions, {
peerInfo
}))
remoteLibp2p = await create(mergeOptions(subsystemOptions, {
peerInfo: remotePeerInfo,
config: {
pubsub: {
enabled: false
}
}
}))
await libp2p.start()
await remoteLibp2p.start()
remAddr = remoteLibp2p.transportManager.getAddrs()[0]
})
afterEach(() => Promise.all([
libp2p && libp2p.stop(),
remoteLibp2p && remoteLibp2p.stop()
]))
afterEach(() => {
sinon.restore()
})
it.skip('should get notified of connected peers after starting', async () => {
const connection = await libp2p.dial(remAddr)
expect(connection).to.exist()
expect(libp2p.pubsub._pubsub.peers.size).to.be.eql(0)
expect(remoteLibp2p.pubsub._pubsub.peers.size).to.be.eql(0)
remoteLibp2p.pubsub.start()
// Wait for
// Validate
expect(libp2p.pubsub._pubsub.peers.size).to.be.eql(1)
expect(remoteLibp2p.pubsub._pubsub.peers.size).to.be.eql(1)
})
it.skip('should receive pubsub messages', async () => {
const defer = pDefer()
const topic = 'test-topic'
const data = 'hey!'
await libp2p.dial(remAddr)
remoteLibp2p.pubsub.start()
// TODO: wait for
libp2p.pubsub.subscribe(topic)
libp2p.pubsub.once(topic, (msg) => {
expect(msg.data.toString()).to.equal(data)
defer.resolve()
})
libp2p.pubsub.publish(topic, data)
await defer.promise
})
})
})

29
test/pubsub/utils.js Normal file
View File

@ -0,0 +1,29 @@
'use strict'
const Gossipsub = require('libp2p-gossipsub')
const { multicodec } = require('libp2p-gossipsub')
const Crypto = require('../../src/insecure/plaintext')
const Muxer = require('libp2p-mplex')
const Transport = require('libp2p-tcp')
const mergeOptions = require('merge-options')
const baseOptions = {
modules: {
transport: [Transport],
streamMuxer: [Muxer],
connEncryption: [Crypto]
}
}
module.exports.baseOptions = baseOptions
const subsystemOptions = mergeOptions(baseOptions, {
modules: {
pubsub: Gossipsub
}
})
module.exports.subsystemOptions = subsystemOptions
module.exports.subsystemMulticodecs = [multicodec]