wip
This commit is contained in:
parent
14c54a2fbf
commit
ee9a3682b4
@ -12,18 +12,17 @@ var assert = require('assert');
|
||||
var BN = require('bn.js');
|
||||
var consensus = require('bcoin').consensus;
|
||||
var constants = require('../../constants');
|
||||
var async = require('async');
|
||||
|
||||
var BlockService = function(options) {
|
||||
BaseService.call(this, options);
|
||||
this._tip = null;
|
||||
this._headerTip = null;
|
||||
this._p2p = this.node.services.p2p;
|
||||
this._db = this.node.services.db;
|
||||
this._subscriptions = {};
|
||||
this._subscriptions.block = [];
|
||||
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({
|
||||
max: 50,
|
||||
length: function(n) {
|
||||
@ -113,6 +112,21 @@ BlockService.prototype.unsubscribe = function(name, emitter) {
|
||||
};
|
||||
|
||||
// --- 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) {
|
||||
|
||||
return this._blockHeaderQueue.get(block.hash) ? true : false;
|
||||
@ -150,13 +164,16 @@ BlockService.prototype._cacheBlock = function(block) {
|
||||
|
||||
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());
|
||||
|
||||
// 2. save to in-memory map block index
|
||||
// 3. save to in-memory map block index
|
||||
this._heightIndex.push(header);
|
||||
|
||||
// 3. get operations
|
||||
// 4. get operations
|
||||
return this._getHeaderOperations(header);
|
||||
|
||||
};
|
||||
@ -470,6 +487,11 @@ BlockService.prototype._isOrphanBlock = function(block) {
|
||||
|
||||
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 start = self._encoding.encodeHashKey(new Array(65).join('0'));
|
||||
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() {
|
||||
var self = this;
|
||||
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) {
|
||||
@ -606,6 +616,8 @@ BlockService.prototype._onTipBlock = function(tip) {
|
||||
|
||||
}
|
||||
|
||||
self._startSync('header');
|
||||
|
||||
};
|
||||
|
||||
BlockService.prototype._reportBootStatus = function() {
|
||||
@ -692,7 +704,7 @@ BlockService.prototype._setTip = function(block) {
|
||||
|
||||
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._numCompleted = currentHeight;
|
||||
if (this._numNeeded <= 0) {
|
||||
@ -750,7 +762,7 @@ BlockService.prototype._sync = function(type) {
|
||||
|
||||
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) + '%)');
|
||||
func.call(this._p2p, obj);
|
||||
return;
|
||||
@ -758,7 +770,8 @@ BlockService.prototype._sync = function(type) {
|
||||
}
|
||||
|
||||
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'));
|
||||
});
|
||||
|
||||
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() {
|
||||
|
||||
it('should detect that a block has already been delivered to us', function() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user