From fde82275576ed6f5ab18a1cb1655dc5b89724b3f Mon Sep 17 00:00:00 2001 From: Rob Brackett Date: Sat, 21 Apr 2018 14:58:19 -0700 Subject: [PATCH 1/2] 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 --- README.md | 2 +- package.json | 2 +- src/core/components/bootstrap.js | 6 +-- src/core/components/init.js | 3 +- ...{config-browser.json => config-browser.js} | 6 ++- .../{config-nodejs.json => config-nodejs.js} | 6 ++- test/bootstrapers.js | 2 +- test/core/create-node.spec.js | 49 +++++++++++++++++++ test/http-api/inject/bootstrap.js | 2 +- 9 files changed, 66 insertions(+), 12 deletions(-) rename src/core/runtime/{config-browser.json => config-browser.js} (96%) rename src/core/runtime/{config-nodejs.json => config-nodejs.js} (98%) diff --git a/README.md b/README.md index 5b32ecb218..944034d8f9 100644 --- a/README.md +++ b/README.md @@ -227,7 +227,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.json b/src/core/runtime/config-browser.js similarity index 96% rename from src/core/runtime/config-browser.json rename to src/core/runtime/config-browser.js index 69114b71bd..c4af756299 100644 --- a/src/core/runtime/config-browser.json +++ b/src/core/runtime/config-browser.js @@ -1,4 +1,6 @@ -{ +'use strict' + +module.exports = () => ({ "Addresses": { "Swarm": [ ], @@ -24,4 +26,4 @@ "/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.js similarity index 98% rename from src/core/runtime/config-nodejs.json rename to src/core/runtime/config-nodejs.js index d1fc0f625d..1eced4bee3 100644 --- a/src/core/runtime/config-nodejs.json +++ b/src/core/runtime/config-nodejs.js @@ -1,4 +1,6 @@ -{ +'use strict' + +module.exports = () => ({ "Addresses": { "Swarm": [ "/ip4/0.0.0.0/tcp/4002", @@ -37,4 +39,4 @@ "/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..1fc43c1896 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', () => { From ec0f4738ee9586b8bf980b4a5a0f052cb645d6da Mon Sep 17 00:00:00 2001 From: Rob Brackett Date: Tue, 24 Apr 2018 11:55:19 -0700 Subject: [PATCH 2/2] Fix lint errors License: MIT Signed-off-by: Rob Brackett --- src/core/runtime/config-browser.js | 38 +++++++++--------- src/core/runtime/config-nodejs.js | 64 +++++++++++++++--------------- test/core/create-node.spec.js | 12 +++--- 3 files changed, 57 insertions(+), 57 deletions(-) diff --git a/src/core/runtime/config-browser.js b/src/core/runtime/config-browser.js index c4af756299..9819c04aaa 100644 --- a/src/core/runtime/config-browser.js +++ b/src/core/runtime/config-browser.js @@ -1,29 +1,29 @@ 'use strict' module.exports = () => ({ - "Addresses": { - "Swarm": [ + Addresses: { + Swarm: [ ], - "API": "", - "Gateway": "" + API: '', + Gateway: '' }, - "Discovery": { - "MDNS": { - "Enabled": false, - "Interval": 10 + Discovery: { + MDNS: { + Enabled: false, + Interval: 10 }, - "webRTCStar": { - "Enabled": true + 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" + 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 index 1eced4bee3..995f66261d 100644 --- a/src/core/runtime/config-nodejs.js +++ b/src/core/runtime/config-nodejs.js @@ -1,42 +1,42 @@ 'use strict' module.exports = () => ({ - "Addresses": { - "Swarm": [ - "/ip4/0.0.0.0/tcp/4002", - "/ip4/127.0.0.1/tcp/4003/ws" + 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" + API: '/ip4/127.0.0.1/tcp/5002', + Gateway: '/ip4/127.0.0.1/tcp/9090' }, - "Discovery": { - "MDNS": { - "Enabled": true, - "Interval": 10 + Discovery: { + MDNS: { + Enabled: true, + Interval: 10 }, - "webRTCStar": { - "Enabled": true + 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" + 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/core/create-node.spec.js b/test/core/create-node.spec.js index 1fc43c1896..7f323abee0 100644 --- a/test/core/create-node.spec.js +++ b/test/core/create-node.spec.js @@ -307,13 +307,13 @@ 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; + + let _nodeNumber = 0 function createNode () { - _nodeNumber++; + _nodeNumber++ return new IPFS({ repo: createTempRepo(), init: { emptyRepo: true }, @@ -330,10 +330,10 @@ describe('create node', function () { } }) } - + const nodeA = createNode() const nodeB = createNode() - + waterfall([ (cb) => parallel([ (cb) => nodeA.once('start', cb),