diff --git a/README.md b/README.md index c7ff99b45f..2a78c854b8 100644 --- a/README.md +++ b/README.md @@ -322,6 +322,18 @@ Enable and configure experimental features. Modify the default IPFS node config. This object will be *merged* with the default config; it will not replace it. +###### Configuring Delegate Routers + +If you need to support Delegated Content and/or Peer Routing, you can enable it by specifying the multiaddrs of your delegate nodes in the config via `options.config.Addresses.Delegates`. If you need to run a delegate router we encourage you to run your own, with go-ipfs. You can see instructions for doing so in the [delegated routing example](https://github.com/libp2p/js-libp2p/tree/master/examples/delegated-routing). + +If you are not able to run your own delegate router nodes, we currently have two nodes that support delegated routing. **Important**: As many people may be leveraging these nodes, performance may be affected, which is why we recommend running your own nodes in production. + +Available delegate multiaddrs are: +- `/dns4/node0.preload.ipfs.io/tcp/443/https` +- `/dns4/node1.preload.ipfs.io/tcp/443/https` + +**Note**: If more than 1 delegate multiaddr is specified, the actual delegate will be randomly selected on startup. + ##### `options.ipld` | Type | Default | diff --git a/package.json b/package.json index 166f0f809e..0cb519b6c6 100644 --- a/package.json +++ b/package.json @@ -122,6 +122,8 @@ "libp2p": "~0.25.3", "libp2p-bootstrap": "~0.9.3", "libp2p-crypto": "~0.16.0", + "libp2p-delegated-content-routing": "^0.2.2", + "libp2p-delegated-peer-routing": "^0.2.2", "libp2p-kad-dht": "~0.15.1", "libp2p-keychain": "~0.4.1", "libp2p-mdns": "~0.12.0", diff --git a/src/core/components/libp2p.js b/src/core/components/libp2p.js index 3ca4b525f3..684bfe2714 100644 --- a/src/core/components/libp2p.js +++ b/src/core/components/libp2p.js @@ -3,6 +3,9 @@ const get = require('dlv') const mergeOptions = require('merge-options') const ipnsUtils = require('../ipns/routing/utils') +const multiaddr = require('multiaddr') +const DelegatedPeerRouter = require('libp2p-delegated-peer-routing') +const DelegatedContentRouter = require('libp2p-delegated-content-routing') module.exports = function libp2p (self, config) { const options = self._options || {} @@ -35,10 +38,34 @@ module.exports = function libp2p (self, config) { } function defaultBundle ({ datastore, peerInfo, peerBook, options, config }) { + // Set up Delegate Routing based on the presence of Delegates in the config + let contentRouting + let peerRouting + const delegateHosts = get(options, 'config.Addresses.Delegates', + get(config, 'Addresses.Delegates', []) + ) + if (delegateHosts.length > 0) { + // Pick a random delegate host + const delegateString = delegateHosts[Math.floor(Math.random() * delegateHosts.length)] + const delegateAddr = multiaddr(delegateString).toOptions() + const delegatedApiOptions = { + host: delegateAddr.host, + // port is a string atm, so we need to convert for the check + protocol: parseInt(delegateAddr.port) === 443 ? 'https' : 'http', + port: delegateAddr.port + } + contentRouting = [new DelegatedContentRouter(peerInfo.id, delegatedApiOptions)] + peerRouting = [new DelegatedPeerRouter(delegatedApiOptions)] + } + const libp2pDefaults = { datastore, peerInfo, peerBook, + modules: { + contentRouting, + peerRouting + }, config: { peerDiscovery: { mdns: { diff --git a/src/core/runtime/config-browser.js b/src/core/runtime/config-browser.js index 1ddbc0d717..537316d431 100644 --- a/src/core/runtime/config-browser.js +++ b/src/core/runtime/config-browser.js @@ -5,7 +5,8 @@ module.exports = () => ({ Swarm: [ ], API: '', - Gateway: '' + Gateway: '', + Delegates: [] }, Discovery: { MDNS: { diff --git a/src/core/runtime/config-nodejs.js b/src/core/runtime/config-nodejs.js index be8115f86a..60169ef562 100644 --- a/src/core/runtime/config-nodejs.js +++ b/src/core/runtime/config-nodejs.js @@ -7,7 +7,8 @@ module.exports = () => ({ '/ip4/127.0.0.1/tcp/4003/ws' ], API: '/ip4/127.0.0.1/tcp/5002', - Gateway: '/ip4/127.0.0.1/tcp/9090' + Gateway: '/ip4/127.0.0.1/tcp/9090', + Delegates: [] }, Discovery: { MDNS: { diff --git a/test/core/libp2p.spec.js b/test/core/libp2p.spec.js index c15173758e..818902d523 100644 --- a/test/core/libp2p.spec.js +++ b/test/core/libp2p.spec.js @@ -222,5 +222,75 @@ describe('libp2p customization', function () { done() }) }) + + it('should NOT create delegate routers if they are not defined', (done) => { + const ipfs = { + _repo: { + datastore + }, + _peerInfo: peerInfo, + _peerBook: peerBook, + // eslint-disable-next-line no-console + _print: console.log, + _options: { + config: { + Addresses: { + Delegates: [] + } + } + } + } + + _libp2p = libp2pComponent(ipfs, testConfig) + + _libp2p.start((err) => { + expect(err).to.not.exist() + + expect(_libp2p._modules.contentRouting).to.not.exist() + expect(_libp2p._modules.peerRouting).to.not.exist() + done() + }) + }) + + it('should create delegate routers if they are defined', (done) => { + const ipfs = { + _repo: { + datastore + }, + _peerInfo: peerInfo, + _peerBook: peerBook, + // eslint-disable-next-line no-console + _print: console.log, + _options: { + config: { + Addresses: { + Delegates: [ + '/dns4/node0.preload.ipfs.io/tcp/443/https' + ] + } + } + } + } + + _libp2p = libp2pComponent(ipfs, testConfig) + + _libp2p.start((err) => { + expect(err).to.not.exist() + + expect(_libp2p._modules.contentRouting).to.have.length(1) + expect(_libp2p._modules.contentRouting[0].api).to.include({ + host: 'node0.preload.ipfs.io', + port: '443', + protocol: 'https' + }) + expect(_libp2p._modules.peerRouting).to.have.length(1) + expect(_libp2p._modules.peerRouting[0].api).to.include({ + host: 'node0.preload.ipfs.io', + port: '443', + protocol: 'https' + }) + done() + }) + }) }) })