From c3d2d1e6c5588725887649df43b77c6a5ad0d7b3 Mon Sep 17 00:00:00 2001 From: Rob Brackett Date: Mon, 30 Apr 2018 00:21:33 -0700 Subject: [PATCH] fix: change default config from JSON file to JS module to prevent having it doubly used (#1324) * Change default config from JSON file to JS module Because the default config was a JSON file, it was treated as a singleton object. In some parts of the code, data got added to it, leading to race conditions when creating multiple nodes simultaneously. To make that harder to do accidentally, the default config is now a *function* that returns a unique configuration object on each call. Fixes #1316. License: MIT Signed-off-by: Rob Brackett * Fix lint errors License: MIT Signed-off-by: Rob Brackett --- README.md | 2 +- package.json | 2 +- src/core/components/bootstrap.js | 6 ++-- src/core/components/init.js | 3 +- src/core/runtime/config-browser.js | 29 ++++++++++++++++ src/core/runtime/config-browser.json | 27 --------------- src/core/runtime/config-nodejs.js | 42 ++++++++++++++++++++++++ src/core/runtime/config-nodejs.json | 40 ----------------------- test/bootstrapers.js | 2 +- test/core/create-node.spec.js | 49 ++++++++++++++++++++++++++++ test/http-api/inject/bootstrap.js | 2 +- 11 files changed, 129 insertions(+), 75 deletions(-) create mode 100644 src/core/runtime/config-browser.js delete mode 100644 src/core/runtime/config-browser.json create mode 100644 src/core/runtime/config-nodejs.js delete mode 100644 src/core/runtime/config-nodejs.json diff --git a/README.md b/README.md index 5454073b28..17ba032aca 100644 --- a/README.md +++ b/README.md @@ -231,7 +231,7 @@ Creates and returns an instance of an IPFS node. Use the `options` argument to s - `enabled` (boolean): Make this node a relay (other nodes can connect *through* it). (Default: `false`) - `active` (boolean): Make this an *active* relay node. Active relay nodes will attempt to dial a destination peer even if that peer is not yet connected to the relay. (Default: `false`) -- `config` (object) Modify the default IPFS node config. Find the Node.js defaults at [`src/core/runtime/config-nodejs.json`](https://github.com/ipfs/js-ipfs/tree/master/src/core/runtime/config-nodejs.json) and the browser defaults at [`src/core/runtime/config-browser.json`](https://github.com/ipfs/js-ipfs/tree/master/src/core/runtime/config-browser.json). This object will be *merged* with the default config; it will not replace it. +- `config` (object) Modify the default IPFS node config. Find the Node.js defaults at [`src/core/runtime/config-nodejs.js`](https://github.com/ipfs/js-ipfs/tree/master/src/core/runtime/config-nodejs.js) and the browser defaults at [`src/core/runtime/config-browser.js`](https://github.com/ipfs/js-ipfs/tree/master/src/core/runtime/config-browser.js). This object will be *merged* with the default config; it will not replace it. - `libp2p` (object) add custom modules to the libp2p stack of your node - `modules` (object): diff --git a/package.json b/package.json index 12cc68234e..a1704ee9f1 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "main": "src/core/index.js", "browser": { "./src/core/components/init-assets.js": false, - "./src/core/runtime/config-nodejs.json": "./src/core/runtime/config-browser.json", + "./src/core/runtime/config-nodejs.js": "./src/core/runtime/config-browser.js", "./src/core/runtime/libp2p-nodejs.js": "./src/core/runtime/libp2p-browser.js", "./src/core/runtime/repo-nodejs.js": "./src/core/runtime/repo-browser.js", "./src/core/runtime/dns-nodejs.js": "./src/core/runtime/dns-browser.js", diff --git a/src/core/components/bootstrap.js b/src/core/components/bootstrap.js index 3d816ac946..0db01a9b54 100644 --- a/src/core/components/bootstrap.js +++ b/src/core/components/bootstrap.js @@ -1,6 +1,6 @@ 'use strict' -const defaultNodes = require('../runtime/config-nodejs.json').Bootstrap +const defaultConfig = require('../runtime/config-nodejs.js') const isMultiaddr = require('mafmt').IPFS.matches const promisify = require('promisify-es6') @@ -41,7 +41,7 @@ module.exports = function bootstrap (self) { return callback(err) } if (args.default) { - config.Bootstrap = defaultNodes + config.Bootstrap = defaultConfig().Bootstrap } else if (multiaddr && config.Bootstrap.indexOf(multiaddr) === -1) { config.Bootstrap.push(multiaddr) } @@ -51,7 +51,7 @@ module.exports = function bootstrap (self) { } callback(null, { - Peers: args.default ? defaultNodes : [multiaddr] + Peers: args.default ? defaultConfig().Bootstrap : [multiaddr] }) }) }) diff --git a/src/core/components/init.js b/src/core/components/init.js index 21504c9128..59555f383a 100644 --- a/src/core/components/init.js +++ b/src/core/components/init.js @@ -4,7 +4,7 @@ const peerId = require('peer-id') const waterfall = require('async/waterfall') const parallel = require('async/parallel') const promisify = require('promisify-es6') -const config = require('../runtime/config-nodejs.json') +const defaultConfig = require('../runtime/config-nodejs.js') const Keychain = require('libp2p-keychain') const addDefaultAssets = require('./init-assets') @@ -37,6 +37,7 @@ module.exports = function init (self) { opts.emptyRepo = opts.emptyRepo || false opts.bits = Number(opts.bits) || 2048 opts.log = opts.log || function () {} + const config = defaultConfig() let privateKey waterfall([ // Verify repo does not yet exist. diff --git a/src/core/runtime/config-browser.js b/src/core/runtime/config-browser.js new file mode 100644 index 0000000000..9819c04aaa --- /dev/null +++ b/src/core/runtime/config-browser.js @@ -0,0 +1,29 @@ +'use strict' + +module.exports = () => ({ + Addresses: { + Swarm: [ + ], + API: '', + Gateway: '' + }, + Discovery: { + MDNS: { + Enabled: false, + Interval: 10 + }, + webRTCStar: { + Enabled: true + } + }, + Bootstrap: [ + '/dns4/ams-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd', + '/dns4/lon-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3', + '/dns4/sfo-3.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM', + '/dns4/sgp-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu', + '/dns4/nyc-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm', + '/dns4/nyc-2.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64', + '/dns4/wss0.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic', + '/dns4/wss1.bootstrap.libp2p.io/tcp/443/wss/ipfs/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6' + ] +}) diff --git a/src/core/runtime/config-browser.json b/src/core/runtime/config-browser.json deleted file mode 100644 index 69114b71bd..0000000000 --- a/src/core/runtime/config-browser.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "Addresses": { - "Swarm": [ - ], - "API": "", - "Gateway": "" - }, - "Discovery": { - "MDNS": { - "Enabled": false, - "Interval": 10 - }, - "webRTCStar": { - "Enabled": true - } - }, - "Bootstrap": [ - "/dns4/ams-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", - "/dns4/lon-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3", - "/dns4/sfo-3.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM", - "/dns4/sgp-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", - "/dns4/nyc-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm", - "/dns4/nyc-2.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", - "/dns4/wss0.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic", - "/dns4/wss1.bootstrap.libp2p.io/tcp/443/wss/ipfs/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6" - ] -} diff --git a/src/core/runtime/config-nodejs.js b/src/core/runtime/config-nodejs.js new file mode 100644 index 0000000000..995f66261d --- /dev/null +++ b/src/core/runtime/config-nodejs.js @@ -0,0 +1,42 @@ +'use strict' + +module.exports = () => ({ + Addresses: { + Swarm: [ + '/ip4/0.0.0.0/tcp/4002', + '/ip4/127.0.0.1/tcp/4003/ws' + ], + API: '/ip4/127.0.0.1/tcp/5002', + Gateway: '/ip4/127.0.0.1/tcp/9090' + }, + Discovery: { + MDNS: { + Enabled: true, + Interval: 10 + }, + webRTCStar: { + Enabled: true + } + }, + Bootstrap: [ + '/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z', + '/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', + '/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM', + '/ip4/162.243.248.213/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm', + '/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu', + '/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64', + '/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd', + '/ip4/178.62.61.185/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3', + '/ip4/104.236.151.122/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx', + '/ip6/2604:a880:1:20::1f9:9001/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z', + '/ip6/2604:a880:1:20::203:d001/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM', + '/ip6/2604:a880:0:1010::23:d001/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm', + '/ip6/2400:6180:0:d0::151:6001/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu', + '/ip6/2604:a880:800:10::4a:5001/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64', + '/ip6/2a03:b0c0:0:1010::23:1001/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd', + '/ip6/2a03:b0c0:1:d0::e7:1/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3', + '/ip6/2604:a880:1:20::1d9:6001/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx', + '/dns4/wss0.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic', + '/dns4/wss1.bootstrap.libp2p.io/tcp/443/wss/ipfs/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6' + ] +}) diff --git a/src/core/runtime/config-nodejs.json b/src/core/runtime/config-nodejs.json deleted file mode 100644 index d1fc0f625d..0000000000 --- a/src/core/runtime/config-nodejs.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "Addresses": { - "Swarm": [ - "/ip4/0.0.0.0/tcp/4002", - "/ip4/127.0.0.1/tcp/4003/ws" - ], - "API": "/ip4/127.0.0.1/tcp/5002", - "Gateway": "/ip4/127.0.0.1/tcp/9090" - }, - "Discovery": { - "MDNS": { - "Enabled": true, - "Interval": 10 - }, - "webRTCStar": { - "Enabled": true - } - }, - "Bootstrap": [ - "/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z", - "/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", - "/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM", - "/ip4/162.243.248.213/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm", - "/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", - "/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", - "/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", - "/ip4/178.62.61.185/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3", - "/ip4/104.236.151.122/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx", - "/ip6/2604:a880:1:20::1f9:9001/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z", - "/ip6/2604:a880:1:20::203:d001/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM", - "/ip6/2604:a880:0:1010::23:d001/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm", - "/ip6/2400:6180:0:d0::151:6001/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu", - "/ip6/2604:a880:800:10::4a:5001/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", - "/ip6/2a03:b0c0:0:1010::23:1001/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd", - "/ip6/2a03:b0c0:1:d0::e7:1/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3", - "/ip6/2604:a880:1:20::1d9:6001/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx", - "/dns4/wss0.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic", - "/dns4/wss1.bootstrap.libp2p.io/tcp/443/wss/ipfs/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6" - ] -} diff --git a/test/bootstrapers.js b/test/bootstrapers.js index 49ef1f5d10..ff146e06b7 100644 --- a/test/bootstrapers.js +++ b/test/bootstrapers.js @@ -6,7 +6,7 @@ const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) const IPFS = require('..') -const list = require('../src/core/runtime/config-browser.json').Bootstrap +const list = require('../src/core/runtime/config-browser.js')().Bootstrap /* * These tests were graciously made for lgierth, so that he can test the diff --git a/test/core/create-node.spec.js b/test/core/create-node.spec.js index 03d941ee35..7f323abee0 100644 --- a/test/core/create-node.spec.js +++ b/test/core/create-node.spec.js @@ -7,6 +7,8 @@ const dirtyChai = require('dirty-chai') const expect = chai.expect chai.use(dirtyChai) const series = require('async/series') +const waterfall = require('async/waterfall') +const parallel = require('async/parallel') const os = require('os') const path = require('path') const hat = require('hat') @@ -305,4 +307,51 @@ describe('create node', function () { (cb) => node.stop(cb) ], done) }) + + it('does not share identity with a simultaneously created node', function (done) { + this.timeout(80 * 1000) + + let _nodeNumber = 0 + function createNode () { + _nodeNumber++ + return new IPFS({ + repo: createTempRepo(), + init: { emptyRepo: true }, + config: { + Addresses: { + API: `/ip4/127.0.0.1/tcp/${5010 + _nodeNumber}`, + Gateway: `/ip4/127.0.0.1/tcp/${9090 + _nodeNumber}`, + Swarm: [ + `/ip4/0.0.0.0/tcp/${4010 + _nodeNumber * 2}`, + `/ip4/127.0.0.1/tcp/${4011 + _nodeNumber * 2}/ws` + ] + }, + Bootstrap: [] + } + }) + } + + const nodeA = createNode() + const nodeB = createNode() + + waterfall([ + (cb) => parallel([ + (cb) => nodeA.once('start', cb), + (cb) => nodeB.once('start', cb) + ], cb), + (_, cb) => parallel([ + (cb) => nodeA.id(cb), + (cb) => nodeB.id(cb) + ], cb), + ([idA, idB], cb) => { + expect(idA.id).to.not.equal(idB.id) + cb() + } + ], (error) => { + parallel([ + (cb) => nodeA.stop(cb), + (cb) => nodeB.stop(cb) + ], (stopError) => done(error || stopError)) + }) + }) }) diff --git a/test/http-api/inject/bootstrap.js b/test/http-api/inject/bootstrap.js index 9b9737d39e..33c9f6459d 100644 --- a/test/http-api/inject/bootstrap.js +++ b/test/http-api/inject/bootstrap.js @@ -3,7 +3,7 @@ const expect = require('chai').expect const qs = require('qs') -const defaultList = require('../../../src/core/runtime/config-nodejs.json').Bootstrap +const defaultList = require('../../../src/core/runtime/config-nodejs.js')().Bootstrap module.exports = (http) => { describe('/bootstrap', () => {