diff --git a/lib/scaffold/start.js b/lib/scaffold/start.js index 8dcb2c94..7a187541 100644 --- a/lib/scaffold/start.js +++ b/lib/scaffold/start.js @@ -99,6 +99,7 @@ function lookInBuiltInPath(req, service) { var serviceFile = path.resolve(__dirname, '../services/' + service.name); return req(serviceFile); } catch(e) { + console.log(e); log.info('Checked the built-in path: lib/services, for service: ' + service.name); } } diff --git a/lib/services/block/index.js b/lib/services/block/index.js index 05ff48bb..b73a1ec5 100644 --- a/lib/services/block/index.js +++ b/lib/services/block/index.js @@ -187,7 +187,7 @@ BlockService.prototype._primeBlockQueue = function(callback) { return next(err); } - if (!block) { + if (!data) { return next(); } @@ -220,10 +220,7 @@ BlockService.prototype._detectInitialChainState = function(headers) { }; BlockService.prototype.stop = function(callback) { - if (this._deferTimeout) { - this._deferTimeout.unref(); - } - callback(); + setImmediate(callback); }; BlockService.prototype.subscribe = function(name, emitter) { @@ -267,7 +264,7 @@ BlockService.prototype._broadcast = function(subscribers, name, entity) { BlockService.prototype._cacheBlock = function(block) { - log.debug('Setting block: "' + block.rhash() + '" in the block cache.'); + log.debug('Setting block: ' + block.rhash() + ' in the block cache.'); // 1. set the block queue, which holds full blocks in memory this._blockQueue.set(block.rhash(), block); @@ -318,7 +315,7 @@ BlockService.prototype._findCommonAncestor = function(hash) { // old tip has to be in database self._db.get(self._encoding.encodeBlockKey(_oldTip), function(err, data) { - if (err || !block) { + if (err || !data) { return next(err || new Error('missing block')); } @@ -359,7 +356,7 @@ BlockService.prototype._getBlock = function(hash, callback) { return callback(err); } - if (!block) { + if (!data) { return callback(); } @@ -594,8 +591,6 @@ BlockService.prototype._selectActiveChain = function() { var mostChainWork = new BN(0); var headers = this._header.getAllHeaders(); - var self = this; - if (this._chainTips.length === 1) { return this._chainTips[0]; } @@ -635,13 +630,13 @@ BlockService.prototype._sendDelta = function() { this._setTip({ height: newTipHeight, hash: newTipHash }); var tipOps = utils.encodeTip(this._tip, this.name); - var tipOps = [{ + var ops = [{ type: 'put', key: tipOps.key, value: tipOps.value }]; - this._db.batch(tipOps); + this._db.batch(ops); if (++this._blockCount >= BlockService.MAX_BLOCKS) { this._blockCount = 0; diff --git a/lib/services/db/index.js b/lib/services/db/index.js index 6883c1cf..e0ef62e7 100644 --- a/lib/services/db/index.js +++ b/lib/services/db/index.js @@ -39,6 +39,7 @@ function DB(options) { this._operationsCount = 0; this.GENESIS_HASH = constants.BITCOIN_GENESIS_HASH[this.node.getNetworkName()]; + this.node.on('stopping', function() { log.warn('Node is stopping, gently closing the database.'); }); @@ -222,9 +223,21 @@ DB.prototype.stop = function(callback) { self.close(callback); }; +// for this to work, p2p service has to close out first +// it is feeding more and more ops DB.prototype.close = function(callback) { - if (this._store && this._store.isOpen()) { - this._store.close(callback); + var self = this; + if (self._store && self._store.isOpen()) { + // wait for pending write events to complete before issuing the close event + async.until(function() { + return self._operationsCount <= 0; + }, + function(next) { + setTimeout(next, 1000); + }, + function() { + self._store.close(callback); + }); } }; diff --git a/lib/services/header/index.js b/lib/services/header/index.js index 7d3e0510..bf8e1aa4 100644 --- a/lib/services/header/index.js +++ b/lib/services/header/index.js @@ -85,7 +85,7 @@ HeaderService.prototype.start = function(callback) { }; HeaderService.prototype.stop = function(callback) { - callback(); + setImmediate(callback); }; HeaderService.prototype._startSubscriptions = function() { diff --git a/lib/services/mempool/index.js b/lib/services/mempool/index.js index a29f608f..99a86794 100644 --- a/lib/services/mempool/index.js +++ b/lib/services/mempool/index.js @@ -16,7 +16,7 @@ MempoolService.dependencies = ['db']; MempoolService.prototype.getAPIMethods = function() { var methods = [ - ['getTransaction', this, this.getTransaction, 1] + ['getMempoolTransaction', this, this.getTransaction, 1] ]; return methods; }; @@ -54,21 +54,21 @@ MempoolService.prototype._startSubscriptions = function() { MempoolService.prototype._onBlock = function(block) { // remove this block's txs from mempool - var ops = block.transactions.map(function(tx) { + var ops = block.txs.map(function(tx) { return { type: 'del', - key: tx.id + key: tx.txid() }; }); this._db.batch(ops); }; MempoolService.prototype._onTransaction = function(tx) { - this._db.put(this._encoding.encodeMempoolTransactionKey(tx.id), + this._db.put(this._encoding.encodeMempoolTransactionKey(tx.txid()), this._encoding.encodeMempoolTransactionValue(tx)); }; -MempoolService.prototype.getTransaction = function(txid, callback) { +MempoolService.prototype.getMempoolTransaction = function(txid, callback) { this._db.get(this._encoding.encodeMempoolTransactionKey(txid), callback); }; diff --git a/lib/services/p2p/index.js b/lib/services/p2p/index.js index 8088092b..4cbec45a 100644 --- a/lib/services/p2p/index.js +++ b/lib/services/p2p/index.js @@ -117,12 +117,15 @@ P2P.prototype.start = function(callback) { }; +P2P.prototype._disconnectPool = function() { + + log.info('P2P Service: disconnecting pool and peers. SIGINT issued, system shutdown initiated'); + this._pool.disconnect(); + +}; + P2P.prototype.stop = function(callback) { - - var self = this; - self._pool.disconnect(); - callback(); - + setImmediate(callback); }; P2P.prototype.subscribe = function(name, emitter) { @@ -300,6 +303,7 @@ P2P.prototype._removePeer = function(peer) { P2P.prototype._setListeners = function() { var self = this; + self.node.on('stopping', self._disconnectPool.bind(self)); self._pool.on('peerready', self._onPeerReady.bind(self)); self._pool.on('peerdisconnect', self._onPeerDisconnect.bind(self)); self._pool.on('peerinv', self._onPeerInventory.bind(self)); diff --git a/lib/services/timestamp/index.js b/lib/services/timestamp/index.js index 49517f5f..79bab071 100644 --- a/lib/services/timestamp/index.js +++ b/lib/services/timestamp/index.js @@ -25,8 +25,7 @@ TimestampService.dependencies = [ 'db', 'block' ]; TimestampService.prototype.getAPIMethods = function() { return [ - ['getBlockHashesByTimestamp', this, this.getBlockHashesByTimestamp, 2], - ['syncPercentage', this, this.syncPercentage, 0] + ['getBlockHashesByTimestamp', this, this.getBlockHashesByTimestamp, 2] ]; }; @@ -140,9 +139,7 @@ TimestampService.prototype._sync = function() { TimestampService.prototype._setListeners = function() { var self = this; - - self._db.on('error', self._onDbError.bind(self)); - self.on('reorg', self._handleReorg.bind(self)); + self.on('reorg', self._onReorg.bind(self)); }; @@ -161,7 +158,7 @@ TimestampService.prototype._onBlock = function(block) { var operations = []; - var ts = block.header.timestamp; + var ts = block.ts; if (ts <= this._lastBlockTimestamp) { ts = this._lastBlockTimestamp + 1; @@ -178,13 +175,13 @@ TimestampService.prototype._onBlock = function(block) { operations = operations.concat([ { type: 'put', - key: this.encoding.encodeTimestampBlockKey(ts), - value: this.encoding.encodeTimestampBlockValue(block.hash) + key: this._encoding.encodeTimestampBlockKey(ts), + value: this._encoding.encodeTimestampBlockValue(block.hash) }, { type: 'put', - key: this.encoding.encodeBlockTimestampKey(block.hash), - value: this.encoding.encodeBlockTimestampValue(ts) + key: this._encoding.encodeBlockTimestampKey(block.hash), + value: this._encoding.encodeBlockTimestampValue(ts) }, { type: 'put', diff --git a/lib/services/transaction/index.js b/lib/services/transaction/index.js index 8d80925f..f34bd1bc 100644 --- a/lib/services/transaction/index.js +++ b/lib/services/transaction/index.js @@ -1,12 +1,12 @@ 'use strict'; -var async = require('async'); var BaseService = require('../../service'); var inherits = require('util').inherits; var Encoding = require('./encoding'); -var utils = require('../../lib/utils'); +var utils = require('../../utils'); var _ = require('lodash'); var LRU = require('lru-cache'); +var Unit = require('bitcore-lib').Unit; function TransactionService(options) { BaseService.call(this, options); @@ -34,7 +34,6 @@ TransactionService.prototype.getAPIMethods = function() { ['getRawTransaction', this, this.getRawTransaction, 1], ['getTransaction', this, this.getTransaction, 1], ['getDetailedTransaction', this, this.getDetailedTransaction, 1], - ['sendTransaction', this, this.sendTransaction, 1], ['syncPercentage', this, this.syncPercentage, 0], ['getInputValues', this, this._getInputValues, 1] ]; @@ -130,10 +129,10 @@ TransactionService.prototype.syncPercentage = function(callback) { TransactionService.prototype._cacheOutputValues = function(tx) { var values = tx.outputs.map(function(output) { - return output.satoshis; + return Unit.fromBTC(output.value).toSatoshis(); }); - this._inputValuesCache.set(tx.id, values); + this._inputValuesCache.set(tx.txid(), values); }; @@ -143,10 +142,12 @@ TransactionService.prototype._getBlockTimestamp = function(hash) { TransactionService.prototype._getInputValues = function(tx) { + var self = this; + return tx.inputs.map(function(input) { - var value = this._inputValuesCache.get(input.prevTxId); + var value = self._inputValuesCache.get(input.prevout.txid()); if (value) { - return value[input.outputIndex]; + return value[input.prevout.index]; } return null; }); @@ -156,7 +157,7 @@ TransactionService.prototype._onBlock = function(block) { var self = this; - var operations = block.transactions.map(function(tx) { + var operations = block.txs.map(function(tx) { return self._processTransaction(tx, { block: block }); }); @@ -168,7 +169,7 @@ TransactionService.prototype._onBlock = function(block) { }; -TransactionService.prototype._onReorg = function(oldBlockList, newBlockList, commonAncestor) { +TransactionService.prototype._onReorg = function(oldBlockList, commonAncestor) { // if the common ancestor block height is greater than our own, then nothing to do for the reorg if (this._tip.height <= commonAncestor.header.height) { @@ -197,8 +198,6 @@ TransactionService.prototype._onReorg = function(oldBlockList, newBlockList, com this._db.batch(removalOps); - //call onBlock for each of the new blocks - newBlockList.forEach(this._onBlock.bind(this)); }; TransactionService.prototype._processTransaction = function(tx, opts) { @@ -218,7 +217,7 @@ TransactionService.prototype._processTransaction = function(tx, opts) { tx.__height = opts.block.height; return { - key: this._encoding.encodeTransactionKey(tx.id), + key: this._encoding.encodeTransactionKey(tx.txid()), value: this._encoding.encodeTransactionValue(tx) }; diff --git a/package-lock.json b/package-lock.json index b518617e..f6412963 100644 --- a/package-lock.json +++ b/package-lock.json @@ -145,9 +145,12 @@ "dev": true }, "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", + "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", + "requires": { + "lodash": "4.17.4" + } }, "asynckit": { "version": "0.4.0", @@ -379,13 +382,18 @@ } }, "bitcore-p2p": { - "version": "github:bitpay/bitcore-p2p#126566a57bdd4495868571860e9764bdc85d9fef", + "version": "github:bitpay/bitcore-p2p#f537eb86b9759985822f0f35887642040b1165cb", "requires": { "bcoin": "github:bcoin-org/bcoin#ffec8ff2d7e05591d113004ed1aca6e0c4fd1d20", "bitcore-lib": "0.14.0", "bloom-filter": "0.2.0", "buffers": "github:bitpay/node-buffers#04f4c4264e0d105db2b99b786843ed64f23230d8", "socks5-client": "0.3.6" + }, + "dependencies": { + "buffers": { + "version": "github:bitpay/node-buffers#04f4c4264e0d105db2b99b786843ed64f23230d8" + } } }, "bl": { @@ -495,9 +503,6 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "optional": true }, - "buffers": { - "version": "github:bitpay/node-buffers#04f4c4264e0d105db2b99b786843ed64f23230d8" - }, "bufferutil": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-1.2.1.tgz", @@ -1563,6 +1568,12 @@ "uglify-js": "2.8.29" }, "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, "source-map": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", @@ -1991,6 +2002,12 @@ "wordwrap": "1.0.0" }, "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, "glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", diff --git a/package.json b/package.json index 1d68c81e..3fd4e814 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "wallet backend" ], "dependencies": { - "async": "^1.3.0", + "async": "^2.5.0", "bcoin": "bcoin-org/bcoin#master", "bitcoind-rpc": "^0.6.0", "bitcore-lib": "^0.14",