general: code cleanup, refactoring and formatting

This commit is contained in:
Braydon Fuller 2016-04-27 10:57:37 -04:00
parent c1e9d5a3d9
commit 92bae5f09a
9 changed files with 236 additions and 219 deletions

View File

@ -9,7 +9,7 @@ function main(parentServicesPath, additionalServices) {
moduleName: 'bitcore-node', moduleName: 'bitcore-node',
configName: 'bitcore-node', configName: 'bitcore-node',
processTitle: 'bitcore' processTitle: 'bitcore'
}).on('require', function (name, module) { }).on('require', function (name) {
console.log('Loading:', name); console.log('Loading:', name);
}).on('requireFail', function (name, err) { }).on('requireFail', function (name, err) {
console.log('Unable to load:', name, err); console.log('Unable to load:', name, err);

View File

@ -9,7 +9,7 @@ function main(parentServicesPath, additionalServices) {
moduleName: 'bitcore-node', moduleName: 'bitcore-node',
configName: 'bitcore-node', configName: 'bitcore-node',
processTitle: 'bitcored' processTitle: 'bitcored'
}).on('require', function (name, module) { }).on('require', function (name) {
console.log('Loading:', name); console.log('Loading:', name);
}).on('requireFail', function (name, err) { }).on('requireFail', function (name, err) {
console.log('Unable to load:', name, err); console.log('Unable to load:', name, err);

View File

@ -45,7 +45,7 @@ Logger.prototype.warn = function() {
* Proxies console.log with color and arg parsing magic * Proxies console.log with color and arg parsing magic
* #_log * #_log
*/ */
Logger.prototype._log = function(color, type) { Logger.prototype._log = function(color) {
if (process.env.NODE_ENV === 'test') { if (process.env.NODE_ENV === 'test') {
return; return;
} }

View File

@ -5,177 +5,11 @@ var BitcoreNode = require('../node');
var index = require('../'); var index = require('../');
var bitcore = require('bitcore-lib'); var bitcore = require('bitcore-lib');
var _ = bitcore.deps._; var _ = bitcore.deps._;
var $ = bitcore.util.preconditions;
var log = index.log; var log = index.log;
var child_process = require('child_process');
var fs = require('fs');
var shuttingDown = false; var shuttingDown = false;
log.debug = function() {}; 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 * This function will instantiate and start a Node, requiring the necessary service
* modules, and registering event handlers. * 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 * @param {Number} options.config.port - The port to use for the web service
*/ */
function start(options) { function start(options) {
/* jshint maxstatements: 20 */
var fullConfig = _.clone(options.config); 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 = start;
module.exports.registerExitHandlers = registerExitHandlers; module.exports.registerExitHandlers = registerExitHandlers;
module.exports.exitHandler = exitHandler; module.exports.exitHandler = exitHandler;

View File

@ -78,7 +78,7 @@ Service.prototype.stop = function(done) {
* Setup express routes * Setup express routes
* @param {Express} app * @param {Express} app
*/ */
Service.prototype.setupRoutes = function(app) { Service.prototype.setupRoutes = function() {
// Setup express routes here // Setup express routes here
}; };
@ -86,6 +86,4 @@ Service.prototype.getRoutePrefix = function() {
return this.name; return this.name;
}; };
module.exports = Service; module.exports = Service;

View File

@ -1,7 +1,6 @@
'use strict'; 'use strict';
var fs = require('fs'); var fs = require('fs');
var path = require('path');
var spawn = require('child_process').spawn; var spawn = require('child_process').spawn;
var util = require('util'); var util = require('util');
var mkdirp = require('mkdirp'); var mkdirp = require('mkdirp');
@ -16,7 +15,6 @@ var _ = bitcore.deps._;
var index = require('../'); var index = require('../');
var errors = index.errors; var errors = index.errors;
var log = index.log; var log = index.log;
var utils = require('../utils');
var Service = require('../service'); var Service = require('../service');
var Transaction = require('../transaction'); var Transaction = require('../transaction');
@ -30,6 +28,7 @@ var Transaction = require('../transaction');
* @param {Node} options.node - A reference to the node * @param {Node} options.node - A reference to the node
*/ */
function Bitcoin(options) { function Bitcoin(options) {
/* jshint maxstatements: 20 */
if (!(this instanceof Bitcoin)) { if (!(this instanceof Bitcoin)) {
return new Bitcoin(options); return new Bitcoin(options);
} }
@ -1022,6 +1021,7 @@ Bitcoin.prototype._getHeightRangeQuery = function(options, clone) {
* @param {Function} callback * @param {Function} callback
*/ */
Bitcoin.prototype.getAddressTxids = function(addressArg, options, callback) { Bitcoin.prototype.getAddressTxids = function(addressArg, options, callback) {
/* jshint maxstatements: 16 */
var self = this; var self = this;
var queryMempool = _.isUndefined(options.queryMempool) ? true : options.queryMempool; var queryMempool = _.isUndefined(options.queryMempool) ? true : options.queryMempool;
var rangeQuery = false; var rangeQuery = false;
@ -1091,6 +1091,48 @@ Bitcoin.prototype._getConfirmationsDetail = function(transaction) {
return Math.max(0, confirmations); 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) { Bitcoin.prototype._getAddressDetailsForTransaction = function(transaction, addressStrings) {
var result = { var result = {
addresses: {}, addresses: {},
@ -1099,50 +1141,15 @@ Bitcoin.prototype._getAddressDetailsForTransaction = function(transaction, addre
for (var inputIndex = 0; inputIndex < transaction.inputs.length; inputIndex++) { for (var inputIndex = 0; inputIndex < transaction.inputs.length; inputIndex++) {
var input = transaction.inputs[inputIndex]; var input = transaction.inputs[inputIndex];
if (!input.script) { this._getAddressDetailsForInput(input, inputIndex, result, addressStrings);
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;
}
}
} }
for (var outputIndex = 0; outputIndex < transaction.outputs.length; outputIndex++) { for (var outputIndex = 0; outputIndex < transaction.outputs.length; outputIndex++) {
var output = transaction.outputs[outputIndex]; var output = transaction.outputs[outputIndex];
if (!output.script) { this._getAddressDetailsForOutput(output, outputIndex, result, addressStrings);
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;
}
}
} }
return result; return result;
}; };
/** /**

View File

@ -1,12 +1,13 @@
'use strict';
var Service = require('../lib/service'); var Service = require('../lib/service');
var BitcoreNode = require('../lib/node'); var BitcoreNode = require('../lib/node');
var util = require('util'); var util = require('util');
var EventEmitter = require('events').EventEmitter;
var should = require('chai').should(); var should = require('chai').should();
var TestService = function(options) { var TestService = function(options) {
this.node = options.node; this.node = options.node;
} };
util.inherits(TestService, Service); util.inherits(TestService, Service);
TestService.dependencies = []; TestService.dependencies = [];

View File

@ -24,7 +24,7 @@ var BitcoinService = proxyquire('../../lib/services/bitcoind', {
var defaultBitcoinConf = fs.readFileSync(path.resolve(__dirname, '../data/default.bitcoin.conf'), 'utf8'); var defaultBitcoinConf = fs.readFileSync(path.resolve(__dirname, '../data/default.bitcoin.conf'), 'utf8');
describe('Bitcoin Service', function() { describe('Bitcoin Service', function() {
var txhex = '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000'; var txhex = '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000';
var baseConfig = { var baseConfig = {
node: { node: {

View File

@ -22,15 +22,11 @@ var fakeSocket = new EventEmitter();
fakeSocket.on('test/event1', function(data) { fakeSocket.on('test/event1', function(data) {
data.should.equal('testdata'); data.should.equal('testdata');
done();
}); });
fakeSocketListener.emit('connection', fakeSocket); fakeSocketListener.emit('connection', fakeSocket);
fakeSocket.emit('subscribe', 'test/event1'); fakeSocket.emit('subscribe', 'test/event1');
var WebService = proxyquire('../../lib/services/web', {http: httpStub, https: httpsStub, fs: fsStub}); var WebService = proxyquire('../../lib/services/web', {http: httpStub, https: httpsStub, fs: fsStub});
describe('WebService', function() { describe('WebService', function() {
@ -323,7 +319,7 @@ describe('WebService', function() {
var message = { var message = {
method: 'two', method: 'two',
params: [1, 2] params: [1, 2]
} };
web.socketMessageHandler(message, function(response) { web.socketMessageHandler(message, function(response) {
should.exist(response.error); should.exist(response.error);
response.error.message.should.equal('Method Not Found'); response.error.message.should.equal('Method Not Found');