147 lines
3.4 KiB
JavaScript
147 lines
3.4 KiB
JavaScript
'use strict';
|
|
|
|
var Encoding = require('./encoding');
|
|
var BaseService = require('../../service');
|
|
var inherits = require('util').inherits;
|
|
var LRU = require('lru-cache');
|
|
var utils = require('../../../lib/utils');
|
|
|
|
function TimestampService(options) {
|
|
BaseService.call(this, options);
|
|
this.currentBlock = null;
|
|
this.currentTimestamp = null;
|
|
this._cache = LRU(50);
|
|
var genesis = self.node.services.block.genesis;
|
|
this._cache.set(genesis.hash, genesis.__height);
|
|
}
|
|
|
|
inherits(TimestampService, BaseService);
|
|
|
|
TimestampService.dependencies = [ 'db' ];
|
|
|
|
TimestampService.prototype.start = function(callback) {
|
|
var self = this;
|
|
|
|
this.db = this.node.services.db;
|
|
|
|
this.node.services.db.getPrefix(this.name, function(err, prefix) {
|
|
if(err) {
|
|
return callback(err);
|
|
}
|
|
|
|
self.prefix = prefix;
|
|
self.encoding = new Encoding(self.prefix);
|
|
callback();
|
|
});
|
|
|
|
self.counter = 0;
|
|
};
|
|
|
|
TimestampService.prototype.stop = function(callback) {
|
|
setImmediate(callback);
|
|
};
|
|
|
|
TimestampService.prototype._processBlockHandlerQueue = function(block) {
|
|
|
|
var self = this;
|
|
|
|
var blockTime = block.header.timestamp;
|
|
|
|
var prevHash = utils.reverseBufferToString(block.header.prevHash);
|
|
|
|
var prev = self._cache.get(prevHash);
|
|
|
|
if (prev && !prev.prevHash) {
|
|
|
|
if (blockTime <= prev.time) {
|
|
blockTime++;
|
|
}
|
|
|
|
self._cache.del(prevHash);
|
|
self._cache.set(block.hash, { time: blockTime });
|
|
return [{ hash: block.hash, time: blockTime }];
|
|
}
|
|
|
|
self._cache.set(block.hash, { time: blockTime, prevHash: prevHash });
|
|
|
|
var additionalBlocks = [];
|
|
var dependentHash = block.hash;
|
|
|
|
self._cache.rforEach(function(value, key) {
|
|
if (dependentHash === value.prevHash) {
|
|
additionalBlocks.push({ hash: key, time: value.time });
|
|
dependentHash = value.prevHash;
|
|
self._cache.del(key);
|
|
}
|
|
});
|
|
|
|
return additionalBlocks;
|
|
|
|
};
|
|
|
|
TimestampService.prototype.blockHandler = function(block, connectBlock, callback) {
|
|
|
|
var self = this;
|
|
|
|
var action = connectBlock ? 'put' : 'del';
|
|
|
|
var queue = self._processBlockHandlerQueue(block);
|
|
|
|
var operations = [];
|
|
|
|
if (!queue.length < 1) {
|
|
return callback(null, []);
|
|
}
|
|
|
|
operations = operations.concat([
|
|
{
|
|
type: action,
|
|
key: self.encoding.encodeTimestampBlockKey(timestamp),
|
|
value: self.encoding.encodeTimestampBlockValue(block.header.hash)
|
|
},
|
|
{
|
|
type: action,
|
|
key: self.encoding.encodeBlockTimestampKey(block.header.hash),
|
|
value: self.encoding.encodeBlockTimestampValue(timestamp)
|
|
}
|
|
]);
|
|
|
|
callback(null, operations);
|
|
};
|
|
|
|
TimestampService.prototype.getBlockHeights = function(timestamps, callback) {
|
|
var self = this;
|
|
timestamps.sort();
|
|
timestamps = timestamps.map(function(timestamp) {
|
|
return timestamp >= MAINNET_BITCOIN_GENESIS_TIME ? timestamp : MAINNET_BITCOIN_GENESIS_TIME;
|
|
});
|
|
var start = self.encoding.encodeTimestampBlockKey(timestamps[0]);
|
|
var end = self.encoding.encodeTimestampBlockKey(timestamps[1]);
|
|
var stream = self.db.createReadStream({
|
|
gte: start,
|
|
lte: end
|
|
});
|
|
|
|
var hashes = [];
|
|
var hashTuple = [];
|
|
var streamErr = null;
|
|
|
|
stream.on('data', function(data) {
|
|
hashes.push(self.encoding.decodeTimestampBlockValue(data.value));
|
|
});
|
|
|
|
stream.on('error', function(err) {
|
|
streamErr = err;
|
|
});
|
|
|
|
stream.on('end', function() {
|
|
if (!streamErr && hashes.length > 1) {
|
|
hashTuple = [ hashes[0], hashes[hashes.length - 1] ];
|
|
}
|
|
callback(streamErr, hashTuple);
|
|
});
|
|
|
|
};
|
|
|
|
module.exports = TimestampService;
|