wip
This commit is contained in:
parent
14c54a2fbf
commit
ee9a3682b4
@ -12,18 +12,17 @@ var assert = require('assert');
|
|||||||
var BN = require('bn.js');
|
var BN = require('bn.js');
|
||||||
var consensus = require('bcoin').consensus;
|
var consensus = require('bcoin').consensus;
|
||||||
var constants = require('../../constants');
|
var constants = require('../../constants');
|
||||||
var async = require('async');
|
|
||||||
|
|
||||||
var BlockService = function(options) {
|
var BlockService = function(options) {
|
||||||
BaseService.call(this, options);
|
BaseService.call(this, options);
|
||||||
this._tip = null;
|
this._tip = null;
|
||||||
this._headerTip = null;
|
|
||||||
this._p2p = this.node.services.p2p;
|
this._p2p = this.node.services.p2p;
|
||||||
this._db = this.node.services.db;
|
this._db = this.node.services.db;
|
||||||
this._subscriptions = {};
|
this._subscriptions = {};
|
||||||
this._subscriptions.block = [];
|
this._subscriptions.block = [];
|
||||||
this._subscriptions.reorg = [];
|
this._subscriptions.reorg = [];
|
||||||
this._heightIndex = []; // tracks block height to block hash
|
this._latestHeaderHashReceived = null;
|
||||||
|
this._heightIndex = null; // tracks block height to block hash
|
||||||
this._blockHeaderQueue = LRU({
|
this._blockHeaderQueue = LRU({
|
||||||
max: 50,
|
max: 50,
|
||||||
length: function(n) {
|
length: function(n) {
|
||||||
@ -113,6 +112,21 @@ BlockService.prototype.unsubscribe = function(name, emitter) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// --- start private prototype functions
|
// --- start private prototype functions
|
||||||
|
|
||||||
|
BlockService.prototype._applyHeaderHeights = function() {
|
||||||
|
|
||||||
|
var genesis = constants.BITCOIN_GENESIS_HASH[this.node.getNetworkName()];
|
||||||
|
this._heightIndex = new Array(this._blockHeaderQueue.length + 1);
|
||||||
|
this._heightIndex.push(genesis);
|
||||||
|
|
||||||
|
var _tip = this._latestHeaderHashReceived;
|
||||||
|
while (_tip !== genesis) {
|
||||||
|
this._heightIndex.push(_tip);
|
||||||
|
_tip = this._blockHeaderQueue.get(_tip).prevHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
BlockService.prototype._blockAlreadyProcessed = function(block) {
|
BlockService.prototype._blockAlreadyProcessed = function(block) {
|
||||||
|
|
||||||
return this._blockHeaderQueue.get(block.hash) ? true : false;
|
return this._blockHeaderQueue.get(block.hash) ? true : false;
|
||||||
@ -150,13 +164,16 @@ BlockService.prototype._cacheBlock = function(block) {
|
|||||||
|
|
||||||
BlockService.prototype._cacheHeader = function(header) {
|
BlockService.prototype._cacheHeader = function(header) {
|
||||||
|
|
||||||
// 1. save to in-memory cache first
|
// 1. put a height on the haeder
|
||||||
|
header.height = ++this._latestBlockHeight;
|
||||||
|
|
||||||
|
// 2. save to in-memory cache first
|
||||||
this._blockHeaderQueue.set(header.hash, header.toObject());
|
this._blockHeaderQueue.set(header.hash, header.toObject());
|
||||||
|
|
||||||
// 2. save to in-memory map block index
|
// 3. save to in-memory map block index
|
||||||
this._heightIndex.push(header);
|
this._heightIndex.push(header);
|
||||||
|
|
||||||
// 3. get operations
|
// 4. get operations
|
||||||
return this._getHeaderOperations(header);
|
return this._getHeaderOperations(header);
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -470,6 +487,11 @@ BlockService.prototype._isOrphanBlock = function(block) {
|
|||||||
|
|
||||||
BlockService.prototype._loadHeaders = function(cb) {
|
BlockService.prototype._loadHeaders = function(cb) {
|
||||||
|
|
||||||
|
// on initial sync of headers...we don't have block heights with the headers
|
||||||
|
// we just have a list of headers that have a prevhash pointer and that's about it
|
||||||
|
// we can't be sure that headers have arrived in order, so we can pick the last header
|
||||||
|
// that came in and work backwards to the genesis block. If we don't process exactly the
|
||||||
|
// number of total blocks, then we know we did not really have the last header and we should try again
|
||||||
var self = this;
|
var self = this;
|
||||||
var start = self._encoding.encodeHashKey(new Array(65).join('0'));
|
var start = self._encoding.encodeHashKey(new Array(65).join('0'));
|
||||||
var end = Buffer.concat([ utils.getTerminalKey(start.slice(0, 3)), start.slice(3) ]);
|
var end = Buffer.concat([ utils.getTerminalKey(start.slice(0, 3)), start.slice(3) ]);
|
||||||
@ -513,18 +535,6 @@ BlockService.prototype._loadHeights = function(cb) {
|
|||||||
BlockService.prototype._loadTip = function() {
|
BlockService.prototype._loadTip = function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
self._db.getServiceTip('block');
|
self._db.getServiceTip('block');
|
||||||
async.parallel([
|
|
||||||
self._loadHeaders.bind(self),
|
|
||||||
self._loadHeights.bind(self)
|
|
||||||
], function(err) {
|
|
||||||
if (err) {
|
|
||||||
self._onDbError(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self._setHeaderTip();
|
|
||||||
self._startSubscriptions();
|
|
||||||
self._startSync('header');
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BlockService.prototype._onBestHeight = function(height) {
|
BlockService.prototype._onBestHeight = function(height) {
|
||||||
@ -606,6 +616,8 @@ BlockService.prototype._onTipBlock = function(tip) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self._startSync('header');
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BlockService.prototype._reportBootStatus = function() {
|
BlockService.prototype._reportBootStatus = function() {
|
||||||
@ -692,7 +704,7 @@ BlockService.prototype._setTip = function(block) {
|
|||||||
|
|
||||||
BlockService.prototype._startSync = function(type) {
|
BlockService.prototype._startSync = function(type) {
|
||||||
|
|
||||||
var currentHeight = type === 'block' ? this._tip.height : this._headerTip.height;
|
var currentHeight = type === 'block' ? this._tip.height : 0; //we gather all headers on each boot
|
||||||
this._numNeeded = this._bestHeight - currentHeight;
|
this._numNeeded = this._bestHeight - currentHeight;
|
||||||
this._numCompleted = currentHeight;
|
this._numCompleted = currentHeight;
|
||||||
if (this._numNeeded <= 0) {
|
if (this._numNeeded <= 0) {
|
||||||
@ -750,7 +762,7 @@ BlockService.prototype._sync = function(type) {
|
|||||||
|
|
||||||
if (counter > 0) {
|
if (counter > 0) {
|
||||||
|
|
||||||
log.info(name + ' download progress: ' + this._numCompleted + '/' +
|
log.debug(name + ' download progress: ' + this._numCompleted + '/' +
|
||||||
this._numNeeded + ' (' + (this._numCompleted/this._numNeeded*100).toFixed(2) + '%)');
|
this._numNeeded + ' (' + (this._numCompleted/this._numNeeded*100).toFixed(2) + '%)');
|
||||||
func.call(this._p2p, obj);
|
func.call(this._p2p, obj);
|
||||||
return;
|
return;
|
||||||
@ -758,7 +770,8 @@ BlockService.prototype._sync = function(type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ('header') {
|
if ('header') {
|
||||||
this._startSync('block');
|
// we are done loading headers, proceed to number them
|
||||||
|
this._applyHeaderHeights(this._startSync.bind(this, 'block'));
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -22,6 +22,24 @@ describe('Block Service', function() {
|
|||||||
blockService._encoding = new Encoding(new Buffer('0000', 'hex'));
|
blockService._encoding = new Encoding(new Buffer('0000', 'hex'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe.only('#_applyHeaderHeights', function() {
|
||||||
|
it('should apply heights to the list of headers', function() {
|
||||||
|
var genesis = '0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206';
|
||||||
|
blockService._blockHeaderQueue = LRU(100);
|
||||||
|
blockService._blockHeaderQueue.set(genesis, { prevHash: '00' });
|
||||||
|
blockService._latestHeaderHashReceived = '100';
|
||||||
|
blockService.node = { getNetworkName: function() { return 'regtest'; } };
|
||||||
|
for(var i = 0; i < 99; i++) {
|
||||||
|
var prevHash = i.toString();
|
||||||
|
if (i === 0) {
|
||||||
|
prevHash = genesis;
|
||||||
|
}
|
||||||
|
blockService._blockHeaderQueue.set((i+1).toString(), { prevHash: prevHash });
|
||||||
|
}
|
||||||
|
blockService._applyHeaderHeights();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('#_blockAlreadyProcessed', function() {
|
describe('#_blockAlreadyProcessed', function() {
|
||||||
|
|
||||||
it('should detect that a block has already been delivered to us', function() {
|
it('should detect that a block has already been delivered to us', function() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user