flocore-node/lib/services/timestamp/index.js
2017-05-18 09:48:28 -04:00

132 lines
3.2 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._blockHandlerQueue = LRU(50);
}
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;
//do we have a record in the queue that is waiting on me to consume it?
var prevHash = utils.getPrevHashString(block);
if (prevHash.length !== 64) {
return;
}
var timestamp = self._blockHandlerQueue.get(prevHash);
if (timestamp) {
if (block.header.timestamp <= timestamp) {
timestamp = block.header.timestamp + 1;
}
self.counter++;
timestamp = block.header.timestamp;
self._blockHandlerQueue.del(prevHash);
} else {
timestamp = block.header.timestamp;
}
self._blockHandlerQueue.set(block.hash, timestamp);
return timestamp;
};
TimestampService.prototype.blockHandler = function(block, connectBlock, callback) {
var self = this;
var action = connectBlock ? 'put' : 'del';
var timestamp = self._processBlockHandlerQueue(block);
if (!timestamp) {
return callback(null, []);
}
var operations = [];
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;