diff --git a/lib/contracts/blockchain.js b/lib/contracts/blockchain.js index 65af9d7d3..de84e9af2 100644 --- a/lib/contracts/blockchain.js +++ b/lib/contracts/blockchain.js @@ -2,6 +2,11 @@ const Web3 = require('web3'); const async = require('async'); const Provider = require('./provider.js'); const request = require('request'); +const BlockchainProcessLauncher = require('../processes/blockchainProcessLauncher'); +const utils = require('../utils/utils'); +const constants = require('../constants'); + +const WEB3_READY = 'web3Ready'; class Blockchain { constructor(options) { @@ -12,8 +17,9 @@ class Blockchain { this.blockchainConfig = options.blockchainConfig; this.web3 = options.web3; this.addCheck = options.addCheck; - - this.isWeb3Started = false; + this.web3Endpoint = 'http://' + this.contractsConfig.deployment.host + ':' + this.contractsConfig.deployment.port; + this.isWeb3Ready = false; + this.web3StartedInProcess = false; if (!this.web3) { this.initWeb3(); @@ -24,11 +30,17 @@ class Blockchain { } initWeb3(cb) { + if (!cb) { + cb = function(){}; + } + if (this.isWeb3Ready) { + return cb(); + } const self = this; this.web3 = new Web3(); if (this.contractsConfig.deployment.type === "rpc") { let provider; - self.web3Endpoint = 'http://' + this.contractsConfig.deployment.host + ':' + this.contractsConfig.deployment.port; + const providerOptions = { web3: this.web3, accountsConfig: this.contractsConfig.deployment.accounts, @@ -39,16 +51,56 @@ class Blockchain { provider = new Provider(providerOptions); provider.startWeb3Provider(() => { - self.isWeb3Started = true; - if (cb) { - cb(); - } + self.assertNodeConnection(true, (err) => { + if (err && self.web3StartedInProcess) { + // Already started blockchain in another node, we really have a node problem + self.logger.error(__('Unable to start the blockchain process. Is Geth installed?').red); + return cb(err); + } + if (!err) { + self.isWeb3Ready = true; + self.events.emit(WEB3_READY); + return cb(); + } + self.web3StartedInProcess = true; + self.startBlockchainNode(() => { + // Need to re-initialize web3 to connect to the new blockchain node + provider.stop(); + self.initWeb3(cb); + }); + }); }); } else { throw new Error("contracts config error: unknown deployment type " + this.contractsConfig.deployment.type); } } + onReady(callback) { + if (this.isWeb3Ready) { + return callback(); + } + + this.events.once(WEB3_READY, () => { + callback(); + }); + } + + startBlockchainNode(callback) { + const self = this; + let blockchainProcess = new BlockchainProcessLauncher({ + events: self.events, + logger: self.logger, + normalizeInput: utils.normalizeInput, + blockchainConfig: self.blockchainConfig, + locale: self.locale + }); + + blockchainProcess.startBlockchainNode(); + self.events.once(constants.blockchain.blockchainReady, () => { + callback(); + }); + } + registerServiceCheck() { const self = this; diff --git a/lib/contracts/deploy_manager.js b/lib/contracts/deploy_manager.js index b43825d8d..e59541385 100644 --- a/lib/contracts/deploy_manager.js +++ b/lib/contracts/deploy_manager.js @@ -47,7 +47,7 @@ class DeployManager { // TODO: could be implemented as an event (beforeDeployAll) function checkIsConnectedToBlockchain(callback) { - self.blockchain.initWeb3(() => { + self.blockchain.onReady(() => { self.blockchain.assertNodeConnection((err) => { callback(err); }); diff --git a/lib/core/engine.js b/lib/core/engine.js index 750d6231e..799ab5ab2 100644 --- a/lib/core/engine.js +++ b/lib/core/engine.js @@ -14,7 +14,7 @@ const Watch = require('../pipeline/watch.js'); const LibraryManager = require('../versions/library_manager.js'); const CodeRunner = require('../coderunner/codeRunner.js'); const constants = require('../constants'); -const BlockchainProcess = require('../processes/blockchainProcessLauncher.js'); +const utils = require('../utils/utils'); class Engine { constructor(options) { @@ -50,46 +50,29 @@ class Engine { } } - normalizeInput(input) { - let args = Object.values(input); - if (args.length === 0) { - return ""; - } - if (args.length === 1) { - if (Array.isArray(args[0])) { return args[0].join(','); } - return args[0] || ""; - } - return ('[' + args.map((x) => { - if (x === null) { return "null"; } - if (x === undefined) { return "undefined"; } - if (Array.isArray(x)) { return x.join(','); } - return x; - }).toString() + ']'); - } - doInterceptLogs() { var self = this; let context = {}; context.console = console; context.console.log = function() { - self.logger.info(self.normalizeInput(arguments)); + self.logger.info(utils.normalizeInput(arguments)); }; context.console.warn = function() { - self.logger.warn(self.normalizeInput(arguments)); + self.logger.warn(utils.normalizeInput(arguments)); }; context.console.info = function() { - self.logger.info(self.normalizeInput(arguments)); + self.logger.info(utils.normalizeInput(arguments)); }; context.console.debug = function() { // TODO: ue JSON.stringify - self.logger.debug(self.normalizeInput(arguments)); + self.logger.debug(utils.normalizeInput(arguments)); }; context.console.trace = function() { - self.logger.trace(self.normalizeInput(arguments)); + self.logger.trace(utils.normalizeInput(arguments)); }; context.console.dir = function() { - self.logger.dir(self.normalizeInput(arguments)); + self.logger.dir(utils.normalizeInput(arguments)); }; } @@ -121,7 +104,6 @@ class Engine { "codeRunner": this.codeRunnerService, "codeGenerator": this.codeGeneratorService, "deployment": this.deploymentService, - "processes": this.processesService, "fileWatcher": this.fileWatchService, "webServer": this.webServerService, "ipfs": this.ipfsService, @@ -150,7 +132,6 @@ class Engine { assetFiles: this.config.assetFiles, events: this.events, logger: this.logger, - normalizeInput: this.normalizeInput, plugins: this.plugins }); @@ -166,18 +147,6 @@ class Engine { }); } - processesService(_options) { - let blockchainProcess = new BlockchainProcess({ - events: this.events, - logger: this.logger, - normalizeInput: this.normalizeInput, - blockchainConfig: this.config.blockchainConfig, - locale: this.locale - }); - - blockchainProcess.startBlockchainNode(); - } - codeRunnerService(_options) { this.codeRunner = new CodeRunner({ plugins: this.plugins, diff --git a/lib/i18n/locales/en.json b/lib/i18n/locales/en.json index 234b4cea7..9cbcb2ac1 100644 --- a/lib/i18n/locales/en.json +++ b/lib/i18n/locales/en.json @@ -122,5 +122,6 @@ "successfully uploaded to ipfs": "successfully uploaded to ipfs", "Starting Blockchain node in another process": "Starting Blockchain node in another process", "Blockchain node is ready": "Blockchain node is ready", - "terminating due to error": "terminating due to error" + "terminating due to error": "terminating due to error", + "Unable to start the blockchain process. Is Geth installed?": "Unable to start the blockchain process. Is Geth installed?" } \ No newline at end of file diff --git a/lib/index.js b/lib/index.js index 47e75bd35..3b03d9a46 100644 --- a/lib/index.js +++ b/lib/index.js @@ -129,7 +129,6 @@ class Embark { } engine.startMonitor(); - engine.startService("processes"); engine.startService("libraryManager"); engine.startService("codeRunner"); engine.startService("web3"); diff --git a/lib/pipeline/pipeline.js b/lib/pipeline/pipeline.js index 05f4d5e41..8f6ffd195 100644 --- a/lib/pipeline/pipeline.js +++ b/lib/pipeline/pipeline.js @@ -18,7 +18,6 @@ class Pipeline { this.assetFiles = options.assetFiles; this.events = options.events; this.logger = options.logger; - this.normalizeInput = options.normalizeInput; this.plugins = options.plugins; this.pipelinePlugins = this.plugins.getPluginsFor('pipeline'); } @@ -103,7 +102,7 @@ class Pipeline { modulePath: utils.joinPath(__dirname, 'webpackProcess.js'), logger: self.logger, events: self.events, - normalizeInput: self.normalizeInput + normalizeInput: utils.normalizeInput }); webpackProcess.send({action: constants.pipeline.init, options: {}}); webpackProcess.send({action: constants.pipeline.build, file, importsList}); diff --git a/lib/utils/utils.js b/lib/utils/utils.js index edcb5fa39..f9b0c2449 100644 --- a/lib/utils/utils.js +++ b/lib/utils/utils.js @@ -182,6 +182,23 @@ function sha3(arg) { return Web3.utils.sha3(arg); } +function normalizeInput(input) { + let args = Object.values(input); + if (args.length === 0) { + return ""; + } + if (args.length === 1) { + if (Array.isArray(args[0])) { return args[0].join(','); } + return args[0] || ""; + } + return ('[' + args.map((x) => { + if (x === null) { return "null"; } + if (x === undefined) { return "undefined"; } + if (Array.isArray(x)) { return x.join(','); } + return x; + }).toString() + ']'); +} + module.exports = { joinPath: joinPath, filesMatchingPattern: filesMatchingPattern, @@ -201,5 +218,6 @@ module.exports = { pwd: pwd, getExternalContractUrl, toChecksumAddress: toChecksumAddress, - sha3: sha3 + sha3: sha3, + normalizeInput }; diff --git a/test_apps/test_app/package-lock.json b/test_apps/test_app/package-lock.json index 3dba66074..6a0c2c661 100644 --- a/test_apps/test_app/package-lock.json +++ b/test_apps/test_app/package-lock.json @@ -89,7 +89,7 @@ "dom-helpers": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.3.1.tgz", - "integrity": "sha512-2Sm+JaYn74OiTM2wHvxJOo3roiq/h25Yi69Fqk269cNUwIXsCvATB6CRSFC9Am/20G2b28hGv/+7NiWydIrPvg==" + "integrity": "sha1-/BpOFf/fYN3eA6SAqcD+zoId1KY=" }, "dotenv": { "version": "4.0.0", @@ -229,7 +229,7 @@ "node-fetch": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "integrity": "sha1-mA9vcthSEaU0fGsrwYxbhMPrR+8=", "requires": { "encoding": "0.1.12", "is-stream": "1.1.0" @@ -252,7 +252,7 @@ "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", "requires": { "asap": "2.0.6" } @@ -289,7 +289,7 @@ "react-bootstrap": { "version": "0.32.1", "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-0.32.1.tgz", - "integrity": "sha512-RbfzKUbsukWsToWqGHfCCyMFq9QQI0TznutdyxyJw6dih2NvIne25Mrssg8LZsprqtPpyQi8bN0L0Fx3fUsL8Q==", + "integrity": "sha1-YGJMG0ijnXc+9szmQhpPM+zBZrs=", "requires": { "babel-runtime": "6.26.0", "classnames": "2.2.5", @@ -319,7 +319,7 @@ "react-overlays": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-0.8.3.tgz", - "integrity": "sha512-h6GT3jgy90PgctleP39Yu3eK1v9vaJAW73GOA/UbN9dJ7aAN4BTZD6793eI1D5U+ukMk17qiqN/wl3diK1Z5LA==", + "integrity": "sha1-+tZe6lskMBzKGSoWn13dsLINOsU=", "requires": { "classnames": "2.2.5", "dom-helpers": "3.3.1", @@ -353,7 +353,7 @@ "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=" }, "setimmediate": { "version": "1.0.5", @@ -412,7 +412,7 @@ "zeppelin-solidity": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/zeppelin-solidity/-/zeppelin-solidity-1.8.0.tgz", - "integrity": "sha512-7Mxq6Y7EES0PSLrRF6v0EVYqBVRRo8hFrr7m3jEs69VbbQ5kpANzizeEdbP1/PWKSOmBOg208qP2vSA0FlzFLA==", + "integrity": "sha1-BJ/N59rqn8hSEPjG25+M0auKhTo=", "requires": { "dotenv": "4.0.0", "ethjs-abi": "0.2.1"