From 92bae5f09a259399f755329263ba6970e403fcc9 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Wed, 27 Apr 2016 10:57:37 -0400 Subject: [PATCH] general: code cleanup, refactoring and formatting --- lib/cli/bitcore.js | 2 +- lib/cli/bitcored.js | 2 +- lib/logger.js | 2 +- lib/scaffold/start.js | 347 +++++++++++++++++---------------- lib/service.js | 4 +- lib/services/bitcoind.js | 85 ++++---- test/bus.integration.js | 5 +- test/services/bitcoind.unit.js | 2 +- test/services/web.unit.js | 6 +- 9 files changed, 236 insertions(+), 219 deletions(-) diff --git a/lib/cli/bitcore.js b/lib/cli/bitcore.js index 3ea4771d..bcbaa5ee 100644 --- a/lib/cli/bitcore.js +++ b/lib/cli/bitcore.js @@ -9,7 +9,7 @@ function main(parentServicesPath, additionalServices) { moduleName: 'bitcore-node', configName: 'bitcore-node', processTitle: 'bitcore' - }).on('require', function (name, module) { + }).on('require', function (name) { console.log('Loading:', name); }).on('requireFail', function (name, err) { console.log('Unable to load:', name, err); diff --git a/lib/cli/bitcored.js b/lib/cli/bitcored.js index 158b2ee7..4462a8ea 100644 --- a/lib/cli/bitcored.js +++ b/lib/cli/bitcored.js @@ -9,7 +9,7 @@ function main(parentServicesPath, additionalServices) { moduleName: 'bitcore-node', configName: 'bitcore-node', processTitle: 'bitcored' - }).on('require', function (name, module) { + }).on('require', function (name) { console.log('Loading:', name); }).on('requireFail', function (name, err) { console.log('Unable to load:', name, err); diff --git a/lib/logger.js b/lib/logger.js index eb627650..8d9f48e0 100644 --- a/lib/logger.js +++ b/lib/logger.js @@ -45,7 +45,7 @@ Logger.prototype.warn = function() { * Proxies console.log with color and arg parsing magic * #_log */ -Logger.prototype._log = function(color, type) { +Logger.prototype._log = function(color) { if (process.env.NODE_ENV === 'test') { return; } diff --git a/lib/scaffold/start.js b/lib/scaffold/start.js index fa1365dc..bba6b5de 100644 --- a/lib/scaffold/start.js +++ b/lib/scaffold/start.js @@ -5,177 +5,11 @@ var BitcoreNode = require('../node'); var index = require('../'); var bitcore = require('bitcore-lib'); var _ = bitcore.deps._; -var $ = bitcore.util.preconditions; var log = index.log; -var child_process = require('child_process'); -var fs = require('fs'); var shuttingDown = false; log.debug = function() {}; -/** - * This function will loop over the configuration for services and require the - * specified modules, and assemble an array in this format: - * [ - * { - * name: 'bitcoind', - * config: {}, - * module: BitcoinService - * } - * ] - * @param {Function} req - The require function to use - * @param {Array} servicesPath - The local path (for requiring services) - * @param {Object} config - * @param {Array} config.services - An array of strings of service names. - * @returns {Array} - */ -function setupServices(req, servicesPath, config) { - - module.paths.push(path.resolve(servicesPath, './node_modules')); - - var services = []; - if (config.services) { - for (var i = 0; i < config.services.length; i++) { - var service = {}; - service.name = config.services[i]; - - var hasConfig = config.servicesConfig && config.servicesConfig[service.name]; - service.config = hasConfig ? config.servicesConfig[service.name] : {}; - - try { - // first try in the built-in bitcore-node services directory - service.module = req(path.resolve(__dirname, '../services/' + service.name)); - } catch(e) { - - // check if the package.json specifies a specific file to use - var servicePackage = req(service.name + '/package.json'); - var serviceModule = service.name; - if (servicePackage.bitcoreNode) { - serviceModule = service.name + '/' + servicePackage.bitcoreNode; - } - service.module = req(serviceModule); - } - - // check that the service supports expected methods - if (!service.module.prototype || - !service.module.dependencies || - !service.module.prototype.start || - !service.module.prototype.stop) { - throw new Error( - 'Could not load service "' + service.name + '" as it does not support necessary methods.' - ); - } - - services.push(service); - } - } - return services; -} - -/** - * Will register event handlers to log the current db sync status. - * @param {Node} node - */ -function registerSyncHandlers(node, delay) { - - delay = delay || 10000; - var interval = false; - var count = 0; - - function logSyncStatus() { - log.info( - 'Database Sync Status: Tip:', node.services.db.tip.hash, - 'Height:', node.services.db.tip.__height, - 'Rate:', count/10, 'blocks per second' - ); - } - - node.on('ready', function() { - - if (node.services.db) { - node.on('synced', function() { - clearInterval(interval); - logSyncStatus(); - }); - node.services.db.on('addblock', function(block) { - count++; - // Initialize logging if not already instantiated - if (!interval) { - interval = setInterval(function() { - logSyncStatus(); - count = 0; - }, delay); - } - }); - } - - }); - - node.on('stopping', function() { - clearInterval(interval); - }); -} - -/** - * Will shutdown a node and then the process - * @param {Object} _process - The Node.js process object - * @param {Node} node - The Bitcore Node instance - */ -function cleanShutdown(_process, node) { - node.stop(function(err) { - if(err) { - log.error('Failed to stop services: ' + err); - return _process.exit(1); - } - log.info('Halted'); - _process.exit(0); - }); -} - -/** - * Will register event handlers to stop the node for `process` events - * `uncaughtException` and `SIGINT`. - * @param {Object} _process - The Node.js process - * @param {Node} node - */ -function registerExitHandlers(_process, node) { - //catches uncaught exceptions - _process.on('uncaughtException', exitHandler.bind(null, {exit:true}, _process, node)); - - //catches ctrl+c event - _process.on('SIGINT', exitHandler.bind(null, {sigint:true}, _process, node)); -} - -/** - * Will handle all the shutdown tasks that need to take place to ensure a safe exit - * @param {Object} options - * @param {String} options.sigint - The signal given was a SIGINT - * @param {Array} options.exit - The signal given was an uncaughtException - * @param {Object} _process - The Node.js process - * @param {Node} node - * @param {Error} error -*/ -function exitHandler(options, _process, node, err) { - if (err) { - log.error('uncaught exception:', err); - if(err.stack) { - log.error(err.stack); - } - node.stop(function(err) { - if(err) { - log.error('Failed to stop services: ' + err); - } - _process.exit(-1); - }); - } - if (options.sigint) { - if (!shuttingDown) { - shuttingDown = true; - start.cleanShutdown(_process, node); - } - } -} - /** * This function will instantiate and start a Node, requiring the necessary service * modules, and registering event handlers. @@ -190,6 +24,7 @@ function exitHandler(options, _process, node, err) { * @param {Number} options.config.port - The port to use for the web service */ function start(options) { + /* jshint maxstatements: 20 */ var fullConfig = _.clone(options.config); @@ -242,6 +77,186 @@ function start(options) { } +/** + * Checks a service for the expected methods + * @param {Object} service + */ +function checkService(service) { + // check that the service supports expected methods + if (!service.module.prototype || + !service.module.dependencies || + !service.module.prototype.start || + !service.module.prototype.stop) { + throw new Error( + 'Could not load service "' + service.name + '" as it does not support necessary methods.' + ); + } +} + +/** + * Will require a module from local services directory first + * and then from available node_modules + * @param {Function} req + * @param {Object} service + */ +function loadModule(req, service) { + try { + // first try in the built-in bitcore-node services directory + service.module = req(path.resolve(__dirname, '../services/' + service.name)); + } catch(e) { + + // check if the package.json specifies a specific file to use + var servicePackage = req(service.name + '/package.json'); + var serviceModule = service.name; + if (servicePackage.bitcoreNode) { + serviceModule = service.name + '/' + servicePackage.bitcoreNode; + } + service.module = req(serviceModule); + } +} + +/** + * This function will loop over the configuration for services and require the + * specified modules, and assemble an array in this format: + * [ + * { + * name: 'bitcoind', + * config: {}, + * module: BitcoinService + * } + * ] + * @param {Function} req - The require function to use + * @param {Array} servicesPath - The local path (for requiring services) + * @param {Object} config + * @param {Array} config.services - An array of strings of service names. + * @returns {Array} + */ +function setupServices(req, servicesPath, config) { + + module.paths.push(path.resolve(servicesPath, './node_modules')); + + var services = []; + if (config.services) { + for (var i = 0; i < config.services.length; i++) { + var service = {}; + service.name = config.services[i]; + + var hasConfig = config.servicesConfig && config.servicesConfig[service.name]; + service.config = hasConfig ? config.servicesConfig[service.name] : {}; + + loadModule(req, service); + checkService(service); + + services.push(service); + } + } + return services; +} + +/** + * Will register event handlers to log the current db sync status. + * @param {Node} node + */ +function registerSyncHandlers(node, delay) { + + delay = delay || 10000; + var interval = false; + var count = 0; + + function logSyncStatus() { + log.info( + 'Database Sync Status: Tip:', node.services.db.tip.hash, + 'Height:', node.services.db.tip.__height, + 'Rate:', count/10, 'blocks per second' + ); + } + + node.on('ready', function() { + + if (node.services.db) { + node.on('synced', function() { + clearInterval(interval); + logSyncStatus(); + }); + node.services.db.on('addblock', function() { + count++; + // Initialize logging if not already instantiated + if (!interval) { + interval = setInterval(function() { + logSyncStatus(); + count = 0; + }, delay); + } + }); + } + + }); + + node.on('stopping', function() { + clearInterval(interval); + }); +} + +/** + * Will shutdown a node and then the process + * @param {Object} _process - The Node.js process object + * @param {Node} node - The Bitcore Node instance + */ +function cleanShutdown(_process, node) { + node.stop(function(err) { + if(err) { + log.error('Failed to stop services: ' + err); + return _process.exit(1); + } + log.info('Halted'); + _process.exit(0); + }); +} + +/** + * Will handle all the shutdown tasks that need to take place to ensure a safe exit + * @param {Object} options + * @param {String} options.sigint - The signal given was a SIGINT + * @param {Array} options.exit - The signal given was an uncaughtException + * @param {Object} _process - The Node.js process + * @param {Node} node + * @param {Error} error +*/ +function exitHandler(options, _process, node, err) { + if (err) { + log.error('uncaught exception:', err); + if(err.stack) { + log.error(err.stack); + } + node.stop(function(err) { + if(err) { + log.error('Failed to stop services: ' + err); + } + _process.exit(-1); + }); + } + if (options.sigint) { + if (!shuttingDown) { + shuttingDown = true; + start.cleanShutdown(_process, node); + } + } +} + +/** + * Will register event handlers to stop the node for `process` events + * `uncaughtException` and `SIGINT`. + * @param {Object} _process - The Node.js process + * @param {Node} node + */ +function registerExitHandlers(_process, node) { + //catches uncaught exceptions + _process.on('uncaughtException', exitHandler.bind(null, {exit:true}, _process, node)); + + //catches ctrl+c event + _process.on('SIGINT', exitHandler.bind(null, {sigint:true}, _process, node)); +} + module.exports = start; module.exports.registerExitHandlers = registerExitHandlers; module.exports.exitHandler = exitHandler; diff --git a/lib/service.js b/lib/service.js index cc47ce1a..08d0ef5a 100644 --- a/lib/service.js +++ b/lib/service.js @@ -78,7 +78,7 @@ Service.prototype.stop = function(done) { * Setup express routes * @param {Express} app */ -Service.prototype.setupRoutes = function(app) { +Service.prototype.setupRoutes = function() { // Setup express routes here }; @@ -86,6 +86,4 @@ Service.prototype.getRoutePrefix = function() { return this.name; }; - - module.exports = Service; diff --git a/lib/services/bitcoind.js b/lib/services/bitcoind.js index da702678..b749c89e 100644 --- a/lib/services/bitcoind.js +++ b/lib/services/bitcoind.js @@ -1,7 +1,6 @@ 'use strict'; var fs = require('fs'); -var path = require('path'); var spawn = require('child_process').spawn; var util = require('util'); var mkdirp = require('mkdirp'); @@ -16,7 +15,6 @@ var _ = bitcore.deps._; var index = require('../'); var errors = index.errors; var log = index.log; -var utils = require('../utils'); var Service = require('../service'); var Transaction = require('../transaction'); @@ -30,6 +28,7 @@ var Transaction = require('../transaction'); * @param {Node} options.node - A reference to the node */ function Bitcoin(options) { + /* jshint maxstatements: 20 */ if (!(this instanceof Bitcoin)) { return new Bitcoin(options); } @@ -1022,6 +1021,7 @@ Bitcoin.prototype._getHeightRangeQuery = function(options, clone) { * @param {Function} callback */ Bitcoin.prototype.getAddressTxids = function(addressArg, options, callback) { + /* jshint maxstatements: 16 */ var self = this; var queryMempool = _.isUndefined(options.queryMempool) ? true : options.queryMempool; var rangeQuery = false; @@ -1091,6 +1091,48 @@ Bitcoin.prototype._getConfirmationsDetail = function(transaction) { return Math.max(0, confirmations); }; +Bitcoin.prototype._getAddressDetailsForInput = function(input, inputIndex, result, addressStrings) { + if (!input.script) { + return; + } + var inputAddress = input.script.toAddress(this.node.network); + if (inputAddress) { + var inputAddressString = inputAddress.toString(); + if (addressStrings.indexOf(inputAddressString) >= 0) { + if (!result.addresses[inputAddressString]) { + result.addresses[inputAddressString] = { + inputIndexes: [inputIndex], + outputIndexes: [] + }; + } else { + result.addresses[inputAddressString].inputIndexes.push(inputIndex); + } + result.satoshis -= input.output.satoshis; + } + } +}; + +Bitcoin.prototype._getAddressDetailsForOutput = function(output, outputIndex, result, addressStrings) { + if (!output.script) { + return; + } + var outputAddress = output.script.toAddress(this.node.network); + if (outputAddress) { + var outputAddressString = outputAddress.toString(); + if (addressStrings.indexOf(outputAddressString) >= 0) { + if (!result.addresses[outputAddressString]) { + result.addresses[outputAddressString] = { + inputIndexes: [], + outputIndexes: [outputIndex] + }; + } else { + result.addresses[outputAddressString].outputIndexes.push(outputIndex); + } + result.satoshis += output.satoshis; + } + } +}; + Bitcoin.prototype._getAddressDetailsForTransaction = function(transaction, addressStrings) { var result = { addresses: {}, @@ -1099,50 +1141,15 @@ Bitcoin.prototype._getAddressDetailsForTransaction = function(transaction, addre for (var inputIndex = 0; inputIndex < transaction.inputs.length; inputIndex++) { var input = transaction.inputs[inputIndex]; - if (!input.script) { - continue; - } - var inputAddress = input.script.toAddress(this.node.network); - if (inputAddress) { - var inputAddressString = inputAddress.toString(); - if (addressStrings.indexOf(inputAddressString) >= 0) { - if (!result.addresses[inputAddressString]) { - result.addresses[inputAddressString] = { - inputIndexes: [inputIndex], - outputIndexes: [] - }; - } else { - result.addresses[inputAddressString].inputIndexes.push(inputIndex); - } - result.satoshis -= input.output.satoshis; - } - } + this._getAddressDetailsForInput(input, inputIndex, result, addressStrings); } for (var outputIndex = 0; outputIndex < transaction.outputs.length; outputIndex++) { var output = transaction.outputs[outputIndex]; - if (!output.script) { - continue; - } - var outputAddress = output.script.toAddress(this.node.network); - if (outputAddress) { - var outputAddressString = outputAddress.toString(); - if (addressStrings.indexOf(outputAddressString) >= 0) { - if (!result.addresses[outputAddressString]) { - result.addresses[outputAddressString] = { - inputIndexes: [], - outputIndexes: [outputIndex] - }; - } else { - result.addresses[outputAddressString].outputIndexes.push(outputIndex); - } - result.satoshis += output.satoshis; - } - } + this._getAddressDetailsForOutput(output, outputIndex, result, addressStrings); } return result; - }; /** diff --git a/test/bus.integration.js b/test/bus.integration.js index 98bc8ab5..0573695d 100644 --- a/test/bus.integration.js +++ b/test/bus.integration.js @@ -1,12 +1,13 @@ +'use strict'; + var Service = require('../lib/service'); var BitcoreNode = require('../lib/node'); var util = require('util'); -var EventEmitter = require('events').EventEmitter; var should = require('chai').should(); var TestService = function(options) { this.node = options.node; -} +}; util.inherits(TestService, Service); TestService.dependencies = []; diff --git a/test/services/bitcoind.unit.js b/test/services/bitcoind.unit.js index 1699e554..7f030668 100644 --- a/test/services/bitcoind.unit.js +++ b/test/services/bitcoind.unit.js @@ -24,7 +24,7 @@ var BitcoinService = proxyquire('../../lib/services/bitcoind', { var defaultBitcoinConf = fs.readFileSync(path.resolve(__dirname, '../data/default.bitcoin.conf'), 'utf8'); describe('Bitcoin Service', function() { - var txhex = '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000'; + var txhex = '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000'; var baseConfig = { node: { diff --git a/test/services/web.unit.js b/test/services/web.unit.js index 5415af2d..5a582784 100644 --- a/test/services/web.unit.js +++ b/test/services/web.unit.js @@ -22,15 +22,11 @@ var fakeSocket = new EventEmitter(); fakeSocket.on('test/event1', function(data) { data.should.equal('testdata'); - done(); }); fakeSocketListener.emit('connection', fakeSocket); - fakeSocket.emit('subscribe', 'test/event1'); - - var WebService = proxyquire('../../lib/services/web', {http: httpStub, https: httpsStub, fs: fsStub}); describe('WebService', function() { @@ -323,7 +319,7 @@ describe('WebService', function() { var message = { method: 'two', params: [1, 2] - } + }; web.socketMessageHandler(message, function(response) { should.exist(response.error); response.error.message.should.equal('Method Not Found');