diff --git a/lib/cmds/blockchain/blockchain.js b/lib/cmds/blockchain/blockchain.js index 851aa0ce..dade0d23 100644 --- a/lib/cmds/blockchain/blockchain.js +++ b/lib/cmds/blockchain/blockchain.js @@ -1,5 +1,6 @@ const async = require('async'); -const shelljs = require('shelljs'); +const child_process = require('child_process'); +const _ = require('underscore'); const fs = require('../../core/fs.js'); @@ -62,7 +63,7 @@ Blockchain.prototype.runCommand = function(cmd, options, callback) { if (this.blockchainConfig.silent) { options.silent = true; } - return shelljs.exec(cmd, options, callback); + return child_process.exec(cmd, options, callback); }; Blockchain.prototype.run = function() { @@ -95,41 +96,59 @@ Blockchain.prototype.run = function() { next(); }, function getMainCommand(next) { - self.client.mainCommand(address, function(cmd) { - next(null, cmd); - }); + self.client.mainCommand(address, function(cmd, args) { + next(null, cmd, args); + }, true); } - ], function (err, cmd) { + ], function (err, cmd, args) { if (err) { console.error(err); return; } - const child = self.runCommand(cmd, {}, (err, stdout, _stderr) => { - if (err && self.env === 'development' && stdout.indexOf('Failed to unlock') > 0) { - // console.error is captured and sent to the console output regardless of silent setting + console.error(cmd); + args = _.compact(args); + + /*cmd = cmd.replace(/"/g, '').split(' --'); + let args = _.compact(cmd.splice(1)).map(arg => { + return '--' + arg; + }); + console.error('CMD', cmd[0]);*/ + console.error('ARGS', args); + + console.log('CWD', process.cwd()); + const child = child_process.spawn(cmd, args, {cwd: process.cwd()}); + + child.on('error', (err) => { + err = err.toString(); + console.error('ERROR', err); + if (self.env === 'development' && err.indexOf('Failed to unlock') > 0) { console.error('\n' + __('Development blockchain has changed to use the --dev option.').yellow); console.error(__('You can reset your workspace to fix the problem with').yellow + ' embark reset'.cyan); console.error(__('Otherwise, you can change your data directory in blockchain.json (datadir)').yellow); } }); - if (self.onReadyCallback) { - // Geth logs appear in stderr somehow - let lastMessage; - child.stderr.on('data', (data) => { - if (!self.readyCalled && data.indexOf('Mapped network port') > -1) { - self.readyCalled = true; - self.onReadyCallback(); - } - lastMessage = data; - console.log('Geth: ' + data); - }); - child.on('exit', (code) => { - if (code) { - console.error('Geth exited with error code ' + code); + // Geth logs appear in stderr somehow + let lastMessage; + child.stdout.on('data', (data) => { + console.log(`Geth error: ${data}`); + }); + child.stderr.on('data', (data) => { + data = data.toString(); + if (self.onReadyCallback && !self.readyCalled && data.indexOf('Mapped network port') > -1) { + self.readyCalled = true; + self.onReadyCallback(); + } + lastMessage = data; + console.log('Geth: ' + data); + }); + child.on('exit', (code) => { + if (code) { + console.error('Geth exited with error code ' + code); + if (lastMessage) { console.error(lastMessage); } - }); - } + } + }); }); }; diff --git a/lib/cmds/blockchain/geth_commands.js b/lib/cmds/blockchain/geth_commands.js index e64f47a6..612170b9 100644 --- a/lib/cmds/blockchain/geth_commands.js +++ b/lib/cmds/blockchain/geth_commands.js @@ -12,28 +12,28 @@ class GethCommands { commonOptions() { let config = this.config; - let cmd = ""; + let cmd = []; - cmd += this.determineNetworkType(config); + cmd.push(this.determineNetworkType(config)); if (config.datadir) { - cmd += "--datadir=\"" + config.datadir + "\" "; + cmd.push("--datadir=" + config.datadir); } if (config.light) { - cmd += "--light "; + cmd.push("--light"); } if (config.fast) { - cmd += "--fast "; + cmd.push("--fast"); } if (config.account && config.account.password) { - cmd += "--password " + config.account.password + " "; + cmd.push("--password=" + config.account.password); } if (Number.isInteger(config.verbosity) && config.verbosity >=0 && config.verbosity <= 5) { - cmd += "--verbosity " + config.verbosity + " "; + cmd.push("--verbosity=" + config.verbosity); } return cmd; @@ -44,20 +44,20 @@ class GethCommands { } determineNetworkType(config) { - let cmd = ""; + let cmd; if (config.networkType === 'testnet') { - cmd += "--testnet "; + cmd = "--testnet "; } else if (config.networkType === 'olympic') { - cmd += "--olympic "; + cmd = "--olympic "; } else if (config.networkType === 'custom') { - cmd += "--networkid " + config.networkId + " "; + cmd = "--networkid=" + config.networkId; } return cmd; } initGenesisCommmand() { let config = this.config; - let cmd = this.geth_bin + " " + this.commonOptions(); + let cmd = this.geth_bin + " " + this.commonOptions().join(' '); if (config.genesisBlock) { cmd += "init \"" + config.genesisBlock + "\" "; @@ -67,20 +67,20 @@ class GethCommands { } newAccountCommand() { - return this.geth_bin + " " + this.commonOptions() + "account new "; + return this.geth_bin + " " + this.commonOptions().join(' ') + "account new "; } listAccountsCommand() { - return this.geth_bin + " " + this.commonOptions() + "account list "; + return this.geth_bin + " " + this.commonOptions().join(' ') + "account list "; } determineRpcOptions(config) { - let cmd = ""; + let cmd = []; - cmd += "--port " + config.port + " "; - cmd += "--rpc "; - cmd += "--rpcport " + config.rpcPort + " "; - cmd += "--rpcaddr " + config.rpcHost + " "; + cmd.push("--port=" + config.port); + cmd.push("--rpc"); + cmd.push("--rpcport=" + config.rpcPort); + cmd.push("--rpcaddr=" + config.rpcHost); if (config.rpcCorsDomain) { if (config.rpcCorsDomain === '*') { console.log('=================================='); @@ -88,7 +88,7 @@ class GethCommands { console.log(__('make sure you know what you are doing')); console.log('=================================='); } - cmd += "--rpccorsdomain=\"" + config.rpcCorsDomain + "\" "; + cmd.push("--rpccorsdomain=\"" + config.rpcCorsDomain + "\""); } else { console.log('=================================='); console.log(__('warning: cors is not set')); @@ -99,12 +99,12 @@ class GethCommands { } determineWsOptions(config) { - let cmd = ""; + let cmd = []; if (config.wsRPC) { - cmd += "--ws "; - cmd += "--wsport " + config.wsPort + " "; - cmd += "--wsaddr " + config.wsHost + " "; + cmd.push("--ws"); + cmd.push("--wsport=" + config.wsPort); + cmd.push("--wsaddr=" + config.wsHost); if (config.wsOrigins) { if (config.wsOrigins === '*') { console.log('=================================='); @@ -112,7 +112,7 @@ class GethCommands { console.log(__('make sure you know what you are doing')); console.log('=================================='); } - cmd += "--wsorigins \"" + config.wsOrigins + "\" "; + cmd.push("--wsorigins=\"" + config.wsOrigins + "\""); } else { console.log('=================================='); console.log(__('warning: wsOrigins is not set')); @@ -129,44 +129,54 @@ class GethCommands { let rpc_api = (this.config.rpcApi || ['eth', 'web3', 'net']); let ws_api = (this.config.wsApi || ['eth', 'web3', 'net']); + let args = []; + async.series([ function commonOptions(callback) { let cmd = self.commonOptions(); + args = args.concat(cmd); callback(null, cmd); }, function rpcOptions(callback) { let cmd = self.determineRpcOptions(self.config); + args = args.concat(cmd); callback(null, cmd); }, function wsOptions(callback) { let cmd = self.determineWsOptions(self.config); + args = args.concat(cmd); callback(null, cmd); }, function dontGetPeers(callback) { if (config.nodiscover) { + args.push("--nodiscover"); return callback(null, "--nodiscover"); } callback(null, ""); }, function vmDebug(callback) { if (config.vmdebug) { + args.push("--vmdebug"); return callback(null, "--vmdebug"); } callback(null, ""); }, function maxPeers(callback) { - let cmd = "--maxpeers " + config.maxpeers; + let cmd = "--maxpeers=" + config.maxpeers; + args.push(cmd); callback(null, cmd); }, function mining(callback) { if (config.mineWhenNeeded || config.mine) { - return callback(null, "--mine "); + args.push("--mine"); + return callback(null, "--mine"); } callback(""); }, function bootnodes(callback) { if (config.bootnodes && config.bootnodes !== "" && config.bootnodes !== []) { - return callback(null, "--bootnodes " + config.bootnodes); + args.push("--bootnodes=" + config.bootnodes); + return callback(null, "--bootnodes=" + config.bootnodes); } callback(""); }, @@ -176,15 +186,18 @@ class GethCommands { if (ws_api.indexOf('shh') === -1) { ws_api.push('shh'); } + args.push("--shh"); return callback(null, "--shh "); } callback(""); }, function rpcApi(callback) { - callback(null, '--rpcapi "' + rpc_api.join(',') + '"'); + args.push('--rpcapi="' + rpc_api.join(',') + '"'); + callback(null, '--rpcapi="' + rpc_api.join(',') + '"'); }, function wsApi(callback) { - callback(null, '--wsapi "' + ws_api.join(',') + '"'); + args.push('--wsapi="' + ws_api.join(',') + '"'); + callback(null, '--wsapi="' + ws_api.join(',') + '"'); }, function accountToUnlock(callback) { let accountAddress = ""; @@ -194,33 +207,37 @@ class GethCommands { accountAddress = address; } if (accountAddress && !self.isDev) { + args.push("--unlock=" + accountAddress); return callback(null, "--unlock=" + accountAddress); } callback(null, ""); }, function gasLimit(callback) { if (config.targetGasLimit) { - return callback(null, "--targetgaslimit " + config.targetGasLimit); + args.push("--targetgaslimit=" + config.targetGasLimit); + return callback(null, "--targetgaslimit=" + config.targetGasLimit); } callback(null, ""); }, function mineWhenNeeded(callback) { if (config.mineWhenNeeded && !self.isDev) { + args.push("js .embark/" + self.env + "/js/mine.js"); return callback(null, "js .embark/" + self.env + "/js/mine.js"); } callback(null, ""); }, function isDev(callback) { if (self.isDev) { + args.push('--dev'); return callback(null, '--dev'); } callback(null, ''); } - ], function (err, results) { + ], function (err) { if (err) { throw new Error(err.message); } - done(self.geth_bin + " " + results.join(" ")); + return done(self.geth_bin, args); }); } } diff --git a/lib/processes/blockchainProcessLauncher.js b/lib/processes/blockchainProcessLauncher.js index 8c2203b4..b677f81a 100644 --- a/lib/processes/blockchainProcessLauncher.js +++ b/lib/processes/blockchainProcessLauncher.js @@ -14,11 +14,11 @@ class BlockchainProcessLauncher { } processEnded(code) { - this.logger.error('Blockchain process ended before the end of this process. Code: ' + code); + this.logger.error(__('Blockchain process ended before the end of this process. Code: %s', code)); } startBlockchainNode() { - this.logger.info('Starting Blockchain node in another process'.cyan); + this.logger.info(__('Starting Blockchain node in another process').cyan); this.blockchainProcess = new ProcessLauncher({ modulePath: utils.joinPath(__dirname, '../cmds/blockchain/blockchainProcess.js'), @@ -40,7 +40,7 @@ class BlockchainProcessLauncher { }); this.blockchainProcess.once('result', constants.blockchain.blockchainReady, () => { - this.logger.info('Blockchain node is ready'.cyan); + this.logger.info(__('Blockchain node is ready').cyan); this.events.emit(constants.blockchain.blockchainReady); }); }