From ee97cb5b12c838a5f4272fad8ccf05caeca280d2 Mon Sep 17 00:00:00 2001 From: Chris Kleeschulte Date: Tue, 26 Sep 2017 11:05:24 -0400 Subject: [PATCH] Added fixes for reorg and added time since last block. --- : | 135 -------------------------- lib/services/block/index.js | 9 +- lib/services/header/encoding.js | 2 +- lib/services/header/index.js | 7 +- lib/utils.js | 30 ++++++ test/services/header/encoding.unit.js | 10 +- test/services/header/index.unit.js | 3 +- test/utils.unit.js | 11 +++ 8 files changed, 60 insertions(+), 147 deletions(-) delete mode 100644 : diff --git a/: b/: deleted file mode 100644 index be9a51b5..00000000 --- a/: +++ /dev/null @@ -1,135 +0,0 @@ -'use strict'; -var BaseService = require('../../service'); -var util = require('util'); -var Encoding = require('./encoding'); -var log = require('../..').log; - -var MempoolService = function(options) { - BaseService.call(this, options); - this._subscriptions = {}; - this._subscriptions.transaction = []; - this._db = this.node.services.db; - this._p2p = this.node.services.p2p; -}; - -util.inherits(MempoolService, BaseService); - -MempoolService.dependencies = ['db']; - -MempoolService.prototype.getAPIMethods = function() { - var methods = [ - ['getMempoolTransaction', this, this.getMempoolTransaction, 1] - ]; - return methods; -}; - -MempoolService.prototype.start = function(callback) { - var self = this; - - self._db.getPrefix(self.name, function(err, prefix) { - if(err) { - return callback(err); - } - self._encoding = new Encoding(prefix); - self._startSubscriptions(); - - callback(); - }); -}; - -MempoolService.prototype.onReorg = function(args, callback) { - - var oldBlockList = args[1]; - - var removalOps = []; - - for(var i = 0; i < oldBlockList.length; i++) { - - var block = oldBlockList[i]; - - for(var j = 0; j < block.txs.length; j++) { - - var tx = block.txs[j]; - var key = this._encoding.encodeMempoolTransactionKey(tx.txid()); - var value = this._encoding.encodeMempoolTransactionValue(tx); - - removalOps.push({ - type: 'put', - key: key, - value: value - }); - - } - } - - setImmediate(function() { - callback(null, removalOps); - }); -}; - -MempoolService.prototype._startSubscriptions = function() { - - var self = this; - if (self._subscribed) { - return; - } - - self._subscribed = true; - if (!self._bus) { - self._bus = self.node.openBus({remoteAddress: 'localhost-mempool'}); - } - - self._bus.on('p2p/transaction', self._onTransaction.bind(self)); - self._bus.subscribe('p2p/transaction'); - - self._p2p.on('bestHeight', function() { - log.info('Mempool Service: Geting mempool from peer.'); - self._p2p.getMempool(); - }); - -}; - -MempoolService.prototype.onBlock = function(block, callback) { - - // remove this block's txs from mempool - var self = this; - var ops = block.txs.map(function(tx) { - return { - type: 'del', - key: self._encoding.encodeMempoolTransactionKey(tx.txid()) - }; - }); - callback(null, ops); - -}; - -MempoolService.prototype._onTransaction = function(tx) { - this._db.put(this._encoding.encodeMempoolTransactionKey(tx.txid()), - this._encoding.encodeMempoolTransactionValue(tx)); -}; - -MempoolService.prototype.getMempoolTransaction = function(txid, callback) { - - var self = this; - - self._db.get(self._encoding.encodeMempoolTransactionKey(txid), function(err, tx) { - - if (err) { - return callback(err); - } - - if (!tx) { - return callback(); - } - - callback(null, self._encoding.decodeMempoolTransactionValue(tx)); - - }); - -}; - -MempoolService.prototype.stop = function(callback) { - callback(); -}; - -module.exports = MempoolService; diff --git a/lib/services/block/index.js b/lib/services/block/index.js index a94cdfc0..a8355d77 100644 --- a/lib/services/block/index.js +++ b/lib/services/block/index.js @@ -188,6 +188,7 @@ BlockService.prototype._checkTip = function(callback) { return callback(); } + log.warn('Block Service: reorganization spotted...'); self._findCommonAncestor(function(err, commonAncestorHash) { if(err) { return callback(err); @@ -366,11 +367,9 @@ BlockService.prototype._queueBlock = function(block) { return self._handleError(err); } - if (Date.now() - self._timeOfLastBlockReport > 30000) { // 30 seconds - self._timeOfLastBlockReport = Date.now(); - log.info('Block Service: The best block hash is: ' + self._tip.hash + - ' at height: ' + self._tip.height); - } + log.info('Block Service: The best block hash is: ' + self._tip.hash + + ' at height: ' + self._tip.height + ' Time since last block: ' + utils.convertMillisecondsToHumanReadable(Date.now() - self._timeOfLastBlockReport)); + self._timeOfLastBlockReport = Date.now(); log.debug('Block Service: completed processing block: ' + block.rhash() + ' prev hash: ' + bcoin.util.revHex(block.prevBlock) + ' height: ' + self._tip.height); diff --git a/lib/services/header/encoding.js b/lib/services/header/encoding.js index 9a7ca77a..0dd7f1d3 100644 --- a/lib/services/header/encoding.js +++ b/lib/services/header/encoding.js @@ -67,7 +67,7 @@ Encoding.prototype.decodeHeaderValue = function(buffer) { var bits = buffer.readUInt32BE(104); var nonce = buffer.readUInt32BE(108); var height = buffer.readUInt32BE(112); - var chainwork = buffer.slice(116).toString('hex'); + var chainwork = buffer.slice(116, 116 + 32).toString('hex'); var nextHash = buffer.slice(116 + 32).toString('hex'); return { hash: hash, diff --git a/lib/services/header/index.js b/lib/services/header/index.js index 27d64ddc..3bf2f8f3 100644 --- a/lib/services/header/index.js +++ b/lib/services/header/index.js @@ -395,7 +395,10 @@ HeaderService.prototype._getDBOpForLastHeader = function(nextHeader) { // then put operation for the updated last header (with the next hash) this._lastHeader.nextHash = nextHeader.hash; var keyHash = this._encoding.encodeHeaderHashKey(this._lastHeader.hash); - var keyHeight = this._encoding.encodeHeaderHeightKey(this._lastHeader.hash); + + assert(this._lastHeader.height >= 0, 'Trying to save a header with incorrect height.'); + + var keyHeight = this._encoding.encodeHeaderHeightKey(this._lastHeader.height); var value = this._encoding.encodeHeaderValue(this._lastHeader); return [ { @@ -596,7 +599,7 @@ HeaderService.prototype._detectReorg = function(block, callback) { return callback(null, header); } - log.warn('Block: ' + block.rhash() + 'references: ' + prevHash + + log.warn('Block: ' + block.rhash() + ' references: ' + prevHash + ' as its previous block, yet we have not stored this block in our data set, thus ignoring this block.'); callback(null, false); diff --git a/lib/utils.js b/lib/utils.js index 0e2d60d5..f48b5b65 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -103,4 +103,34 @@ utils.SimpleMap = function SimpleMap() { }; }; +utils.convertMillisecondsToHumanReadable = function(ms) { + var ret = ''; + + if (!ms && ms !== 0) { + return 'invalid number of ms.'; + } + + if (ms >= 60000) { + var minutes = Math.floor(ms / 60000); + var ms = ms % 60000; + } + + if (ms >= 1000) { + var seconds = Math.floor(ms / 1000); + var ms = ms % 1000; + } + + if (minutes) { + ret = minutes + ' minute(s). '; + } + + if (seconds) { + ret += seconds + ' second(s). '; + } + + ret += ms + ' millisecond(s).'; + return ret; + +}; + module.exports = utils; diff --git a/test/services/header/encoding.unit.js b/test/services/header/encoding.unit.js index 2a475db5..301b6c07 100644 --- a/test/services/header/encoding.unit.js +++ b/test/services/header/encoding.unit.js @@ -22,10 +22,12 @@ describe('Header service encoding', function() { bits: 400000, nonce: 123456, height: 123, - chainwork: '0000000000000000000000000000000000000000000000000000000200020002' + chainwork: '0000000000000000000000000000000000000000000000000000000200020002', + nextHash: '91b58f19b6eecba94ed0f6e463e8e334ec0bcda7880e2985c82a8f32e4d03ade' }; var versionBuf = new Buffer(4); var prevHashBuf = new Buffer(header.prevHash, 'hex'); + var nextHashBuf = new Buffer(header.nextHash, 'hex'); var merkleRootBuf = new Buffer(header.merkleRoot, 'hex'); var tsBuf = new Buffer(4); var bitsBuf = new Buffer(4); @@ -67,7 +69,8 @@ describe('Header service encoding', function() { bitsBuf, nonceBuf, heightBuf, - chainBuf + chainBuf, + nextHashBuf ])); }); @@ -81,7 +84,8 @@ describe('Header service encoding', function() { bitsBuf, nonceBuf, heightBuf, - chainBuf + chainBuf, + nextHashBuf ])).should.deep.equal(header); }); }); diff --git a/test/services/header/index.unit.js b/test/services/header/index.unit.js index fd13ac47..7821e550 100644 --- a/test/services/header/index.unit.js +++ b/test/services/header/index.unit.js @@ -134,7 +134,8 @@ describe('Header Service', function() { var saveHeaders = sandbox.stub(headerService, '_saveHeaders'); headerService._tip = { height: 123, hash: 'aa' }; - headerService._lastHeader = { hash: header.prevHash }; + var lastHeader = Object.assign({ height: 1, chainwork: new Array(65).join('0') }, prevHeader); + headerService._lastHeader = lastHeader; headerService._onHeaders(headers); diff --git a/test/utils.unit.js b/test/utils.unit.js index 44dfa630..cc86ce0b 100644 --- a/test/utils.unit.js +++ b/test/utils.unit.js @@ -122,4 +122,15 @@ describe('Utils', function() { map.getLastIndex().should.equal('last value'); }); }); + + describe('#convertMillisecondsToHumanReadable', function() { + it('should convert a number of milliseconds to human readable format', function() { + var actual1 = utils.convertMillisecondsToHumanReadable(164532); + actual1.should.equal('2 minute(s). 44 second(s). 532 millisecond(s).'); + var actual2 = utils.convertMillisecondsToHumanReadable(1); + actual2.should.equal('1 millisecond(s).'); + var actual3 = utils.convertMillisecondsToHumanReadable(null); + actual3.should.equal('invalid number of ms.'); + }); + }); });