Compare commits

..

60 Commits
master ... dev

Author SHA1 Message Date
sairajzero
35f5a82d4b fix 2023-02-06 17:54:47 +05:30
sairajzero
a396c4a24e ws fix 2023-02-06 17:45:32 +05:30
sairajzero
fe9741fdf3 fix 2023-02-06 01:54:41 +05:30
sairajzero
9da18c7073 checkpoint 2023-02-05 23:10:25 +05:30
sairajzero
7663026227 logs 2023-02-05 23:05:12 +05:30
sairajzero
8d4f9f5a6e Update index.js 2023-02-05 23:02:38 +05:30
sairajzero
1d53646101 Inc MAX_TX_QUERY_LIMIT = 100 2023-02-05 22:48:52 +05:30
sairajzero
e5c86ebe5f Update index.js 2023-02-05 22:45:43 +05:30
sairajzero
5ab1214fa4 Update index.js 2023-02-05 22:41:15 +05:30
sairajzero
c5690aa490 Update index.js 2023-02-05 22:30:24 +05:30
sairajzero
40b2e64a8f test 2023-02-05 22:26:53 +05:30
sairajzero
cb89be8263 logging 2023-02-05 19:09:49 +05:30
sairajzero
85c1c02c74 Update index.js 2023-02-05 18:35:32 +05:30
sairajzero
263c892b1d Update index.js 2023-02-05 18:33:21 +05:30
sairajzero
373600dbb9 Update index.js 2023-02-05 18:08:03 +05:30
sairajzero
f05d83ff6d Update index.js 2023-02-05 17:42:22 +05:30
sairajzero
bcfe9741bd Update index.js 2023-02-05 17:04:21 +05:30
sairajzero
a24916243f Update index.js 2023-02-05 16:29:39 +05:30
sairajzero
0b646fe453 Update index.js 2023-02-05 16:23:34 +05:30
sairajzero
76eb2debdd Update index.js 2023-02-05 16:17:45 +05:30
sairajzero
ed79adb910 Update index.js 2023-02-05 16:13:41 +05:30
sairajzero
5e6340be78 log 2023-02-05 06:03:14 +05:30
sairajzero
9b59e5791a Update index.js 2023-02-05 05:58:38 +05:30
sairajzero
cf9aaae4f6 Update index.js 2023-02-05 05:56:31 +05:30
sairajzero
6b78cfbfd8 Update index.js 2023-02-05 05:46:15 +05:30
sairajzero
c712b17465 Improvements 2023-02-05 03:14:05 +05:30
sairajzero
729072738b API improvements 2023-02-04 20:34:42 +05:30
sairajzero
450e6b9d21 test log 2023-02-02 18:57:33 +05:30
sairajzero
14e9371306 test log 2023-02-02 18:46:11 +05:30
sairajzero
0b0ba0d630 test 2023-02-02 18:40:42 +05:30
sairajzero
8ca0688153 test log 2023-02-02 18:36:49 +05:30
sairajzero
6347ae261f test 2023-02-02 18:30:32 +05:30
sairajzero
bb54d958bb test log 2023-02-02 18:24:31 +05:30
sairajzero
8729078765 improve handling of duplicate tx query 2023-02-02 18:18:07 +05:30
sairajzero
c32a7cb57a fix 2023-01-28 21:03:56 +05:30
sairajzero
6e9f946607 Update index.js 2023-01-28 21:01:10 +05:30
sairajzero
88c276ad49 fix 2023-01-28 20:20:11 +05:30
sairajzero
40b42019ab log 2023-01-28 19:29:56 +05:30
sairajzero
015dbb650d Update index.js 2023-01-28 19:08:45 +05:30
sairajzero
2c3997d245 Update index.js 2023-01-28 18:32:37 +05:30
sairajzero
def559a86a Update index.js 2023-01-28 18:14:29 +05:30
sairajzero
635c344268 bug fix 2023-01-28 17:24:48 +05:30
sairajzero
f73ccfd02e Update index.js 2023-01-28 17:20:34 +05:30
sairajzero
35c506ac65 Fix: aggregation of duplicate values
Fixed: _aggregateAddressSummaryResult to handle duplicate tx data
2023-01-28 17:18:18 +05:30
sairajzero
eb1c6331d8 resetting _getAddressSummaryResult to old 2023-01-28 16:46:16 +05:30
sairajzero
99a96d3f34 log 2023-01-28 15:49:57 +05:30
sairajzero
aa5d986217 logger 2023-01-28 15:38:24 +05:30
sairajzero
2870fe8aa3 Update index.js 2023-01-28 02:57:07 +05:30
sairajzero
113a12aaf4 Checkpoint 2023-01-28 02:05:53 +05:30
sairajzero
c757c2246b Update package-lock.json 2023-01-28 02:05:21 +05:30
sairajzero
648d627149 log 2023-01-28 01:52:55 +05:30
sairajzero
69a829a6eb Update index.js 2023-01-28 01:46:39 +05:30
sairajzero
09a934f65b test-fix 2023-01-28 01:41:49 +05:30
sairajzero
66fa217f10 log: check-fix 2023-01-28 01:36:08 +05:30
sairajzero
d2bb1c6acb logging 2023-01-28 01:30:44 +05:30
sairajzero
3cd4806d12 logging 2023-01-28 01:24:26 +05:30
sairajzero
2de483ada3 logger 2023-01-28 01:16:07 +05:30
sairajzero
9e0ebda278 logging 2023-01-28 01:10:19 +05:30
sairajzero
f899f5671d Adding debug logs 2023-01-28 01:03:38 +05:30
sairajzero
6e2ffdf298 bug fixes 2023-01-28 00:58:09 +05:30
7 changed files with 449 additions and 935 deletions

View File

@ -2,13 +2,11 @@
function Encoding(servicePrefix) { function Encoding(servicePrefix) {
this.servicePrefix = servicePrefix; this.servicePrefix = servicePrefix;
this.addressIndex = new Buffer('00', 'hex');
this.utxoIndex = new Buffer('01', 'hex');
this.addressCache = new Buffer('fe', 'hex');
} }
Encoding.prototype.encodeAddressIndexKey = function(address, height, txid, index, input, timestamp) { Encoding.prototype.encodeAddressIndexKey = function(address, height, txid, index, input, timestamp) {
var buffers = [this.servicePrefix, this.addressIndex]; var prefix = new Buffer('00', 'hex');
var buffers = [this.servicePrefix, prefix];
var addressSizeBuffer = new Buffer(1); var addressSizeBuffer = new Buffer(1);
addressSizeBuffer.writeUInt8(address.length); addressSizeBuffer.writeUInt8(address.length);
@ -60,7 +58,8 @@ Encoding.prototype.decodeAddressIndexKey = function(buffer) {
}; };
Encoding.prototype.encodeUtxoIndexKey = function(address, txid, outputIndex) { Encoding.prototype.encodeUtxoIndexKey = function(address, txid, outputIndex) {
var buffers = [this.servicePrefix, this.utxoIndex]; var prefix = new Buffer('01', 'hex');
var buffers = [this.servicePrefix, prefix];
var addressSizeBuffer = new Buffer(1); var addressSizeBuffer = new Buffer(1);
addressSizeBuffer.writeUInt8(address.length); addressSizeBuffer.writeUInt8(address.length);
@ -115,53 +114,5 @@ Encoding.prototype.decodeUtxoIndexValue = function(buffer) {
}; };
}; };
Encoding.prototype.encodeAddressCacheKey = function(address) {
return Buffer.concat([this.servicePrefix, this.addressCache, new Buffer(address, 'utf8')]);
}
Encoding.prototype.decodeAddressCacheKey = function(buffer) {
return buffer.slice(3).toString('utf8');
}
Encoding.prototype.encodeAddressCacheValue = function(lastTx, lastBlock, balance, received, sent, txApperances) {
var buffer = [];
var balanceBuffer = new Buffer(8);
balanceBuffer.writeBigUInt64BE(BigInt(balance));
buffer.push(balanceBuffer);
var receivedBuffer = new Buffer(8);
receivedBuffer.writeBigUInt64BE(BigInt(received));
buffer.push(receivedBuffer);
var sentBuffer = new Buffer(8);
sentBuffer.writeBigUInt64BE(BigInt(sent));
buffer.push(sentBuffer);
var txApperancesBuffer = new Buffer(4);
txApperancesBuffer.writeUInt32BE(txApperances);
buffer.push(txApperancesBuffer);
var txidBuffer = new Buffer(lastTx, 'hex');
buffer.push(txidBuffer);
var blkBuffer = new Buffer(lastBlock, 'hex');
buffer.push(blkBuffer);
return Buffer.concat(buffer);
}
Encoding.prototype.decodeAddressCacheValue = function(buffer) {
var balance = parseInt(buffer.readBigUInt64BE(0));
var received = parseInt(buffer.readBigUInt64BE(8));
var sent = parseInt(buffer.readBigUInt64BE(16));
var txApperances = buffer.readUInt32BE(24);
var lastTx = buffer.slice(28, 60).toString('hex'); //28 + 32 (tx hash buffer length) = 60
var lastBlock = buffer.slice(60).toString('hex');
return { lastTx, lastBlock, balance, received, sent, txApperances };
}
module.exports = Encoding; module.exports = Encoding;

View File

@ -16,9 +16,7 @@ var utils = require('../../utils');
var LRU = require('lru-cache'); var LRU = require('lru-cache');
var XXHash = require('xxhash'); var XXHash = require('xxhash');
const MAX_TX_QUERY_LIMIT_HISTORY = 1000; const MAX_TX_QUERY_LIMIT = 100;
const MAX_TX_QUERY_LIMIT_UTXO = 1000;
const MAX_TX_QUERY_LIMIT_SUMMARY = 500;
// See rationale about this cache at function getTxList(next) // See rationale about this cache at function getTxList(next)
const TXID_LIST_CACHE_ITEMS = 250; // nr of items (this translates to: consecutive const TXID_LIST_CACHE_ITEMS = 250; // nr of items (this translates to: consecutive
@ -179,10 +177,10 @@ AddressService.prototype.getAddressHistory = function(addresses, options, stream
var self = this; var self = this;
options = options || {}; options = options || {};
//options.from = options.from || 0; //Deprecated, use `after` and `before` option //options.from = options.from || 0; //Deprecated, use `after` option
//options.to = options.to || 0xffffffff; //Deprecated, use `after` and `before` option //options.to = options.to || 0xffffffff; //Deprecated, use `after` option
if(!_.isFunction(callback)){ //if only 3 args, then streamer is callback if(typeof callback !== 'function'){ //if only 3 args, then streamer is callback
callback = streamer; callback = streamer;
streamer = () => null; //NULL fn streamer = () => null; //NULL fn
} }
@ -191,20 +189,11 @@ AddressService.prototype.getAddressHistory = function(addresses, options, stream
options.queryMempool = true; options.queryMempool = true;
} }
if (_.isUndefined(options.mempoolOnly)) {
options.mempoolOnly = false;
}
if(_.isUndefined(options.reverse)) {
options.reverse = false;
}
var old_support = false;
//Quick support for `from` and `to` options (DEPRECATED! Not recommeded to use) //Quick support for `from` and `to` options (DEPRECATED! Not recommeded to use)
if( !_.isUndefined(options.from) || !_.isUndefined(options.to)) { if( !_.isUndefined(options.from) || !_.isUndefined(options.to)) {
old_support = true; options.old_support = true;
options.from = options.from || 0; options.from = options.from || 0;
options.to = options.to || 0xffffffff; //Max value of to will actually be MAX_TX_QUERY_LIMIT_HISTORY options.to = options.to || 0xffffffff; //Max value of to will actually be MAX_TX_QUERY_LIMIT
} }
if (_.isString(addresses)) { if (_.isString(addresses)) {
@ -218,33 +207,23 @@ AddressService.prototype.getAddressHistory = function(addresses, options, stream
async.eachLimit(addresses, 4, function(address, next) { async.eachLimit(addresses, 4, function(address, next) {
var addr_options = Object.assign({}, options), addr_count = 0; self._streamAddressSummary(address, options, function(err, tx){
self._streamAddressSummary(address, addr_options, function(err, tx){
if(err) if(err)
return log.error(err); return log.error(err);
addr_count++; if(!options.txNotNeeded) {
results.totalCount++;
if(!results.items.some(x => x.txid() === tx.txid())) {//add only if tx not already in array if(!results.items.some(x => x.txid() === tx.txid())) //push only if tx not already in array
if(!options.reverse)
results.items.unshift(tx); //using unshift, so that recent tx (low) are at front results.items.unshift(tx); //using unshift, so that recent tx (low) are at front
else
results.items.push(tx);
}
if(results.items.length > MAX_TX_QUERY_LIMIT) { //remove items from array when overflown
if(results.items.length > MAX_TX_QUERY_LIMIT_HISTORY) { //remove items from array when overflown
results.items.sort((a, b) => (b.__height || 0xffffffff) - (a.__height || 0xffffffff) || b.txid().localeCompare(a.txid())); results.items.sort((a, b) => (b.__height || 0xffffffff) - (a.__height || 0xffffffff) || b.txid().localeCompare(a.txid()));
let del_count = results.items.length - MAX_TX_QUERY_LIMIT_HISTORY; let del_count = options.old_support ? results.items.length : results.items.length - MAX_TX_QUERY_LIMIT;
let start_index = (old_support || options.reverse) ? MAX_TX_QUERY_LIMIT_HISTORY : 0; let start_index = options.old_support ? MAX_TX_QUERY_LIMIT : 0;
results.items.splice(start_index, del_count); results.items.splice(start_index, del_count);
}
results.incomplete = true;
if(!old_support && addr_count >= MAX_TX_QUERY_LIMIT_HISTORY)
addr_options.flag_stop = true; //limit has reached, stop quering db for more tx
} }
@ -254,16 +233,17 @@ AddressService.prototype.getAddressHistory = function(addresses, options, stream
}, function(err) { }, function(err) {
console.debug("END @getAddressHistory");
if (err) { if (err) {
return callback(err); return callback(err);
} }
//sort items in desc block-height, then asc txid (if same height) //sort items in desc block-height, then asc txid (if same height)
results.items.sort((a, b) => (b.__height || 0xffffffff) - (a.__height || 0xffffffff) || b.txid().localeCompare(a.txid())); results.items.sort((a, b) => (b.__height || 0xffffffff) - (a.__height || 0xffffffff) || b.txid().localeCompare(a.txid()));
results.totalCount = results.items.length ; results.totalCount = parseInt(results.totalCount.toFixed());
//Quick support for `from` and `to` options (DEPRECATED! Not recommeded to use) //Quick support for `from` and `to` options (DEPRECATED! Not recommeded to use)
if(old_support) { if(options.old_support) {
results.items = results.items.slice(options.from, options.to); results.items = results.items.slice(options.from, options.to);
} }
@ -323,20 +303,19 @@ AddressService.prototype.getAddressSummary = function(address, options, streamer
var self = this; var self = this;
options = options || {}; options = options || {};
//options.from = options.from || 0; //Deprecated, use `after` and `before` option //options.from = options.from || 0; //Deprecated
//options.to = options.to || 0xffffffff; //Deprecated, use `after` and `before` option //options.to = options.to || 0xffffffff; //Deprecated
options.txNotNeeded = true; //no need to store tx details in result
if (_.isUndefined(options.queryMempool)) { if (_.isUndefined(options.queryMempool)) {
options.queryMempool = true; options.queryMempool = true;
} }
if(!_.isFunction(callback)){ //if only 3 args, then streamer is callback if(typeof callback !== 'function'){ //if only 3 args, then streamer is callback
callback = streamer; callback = streamer;
streamer = () => null; //NULL fn streamer = () => null; //NULL fn
} }
var count = 0;
var result = { var result = {
addrStr: address, addrStr: address,
balance: 0, balance: 0,
@ -351,36 +330,14 @@ AddressService.prototype.getAddressSummary = function(address, options, streamer
txApperances: 0, txApperances: 0,
}; };
var useCache = _.isUndefined(options.after) && _.isUndefined(options.before); self.getAddressHistory(address, options, function(err, tx) {
var lastTx, lastBlock;
self._loadCache(address, result, useCache, function(err, lastCachedTx) {
if(err)
log.error(err);
if(!_.isUndefined(lastCachedTx))
options.after = lastCachedTx;
self._streamAddressSummary(address, options, function(err, tx) {
if(err) if(err)
return log.error(err); return log.error(err);
if(tx) { if(tx)
count++;
self._aggregateAddressSummaryResult(tx, address, result, options); self._aggregateAddressSummaryResult(tx, address, result, options);
if(tx.confirmations) {
lastTx = tx.txid();
lastBlock = tx.blockhash;
}
}
if(count >= MAX_TX_QUERY_LIMIT_SUMMARY) {//stop quering db when limit reached
options.flag_stop = true;
result.incomplete = true;
}
streamer(null, tx); streamer(null, tx);
}, function(err) { }, function(err) {
@ -401,144 +358,10 @@ AddressService.prototype.getAddressSummary = function(address, options, streamer
result.totalSent = Unit.fromSatoshis(result.totalSentSat).toBTC(); result.totalSent = Unit.fromSatoshis(result.totalSentSat).toBTC();
result.unconfirmedBalance = Unit.fromSatoshis(result.unconfirmedBalanceSat).toBTC(); result.unconfirmedBalance = Unit.fromSatoshis(result.unconfirmedBalanceSat).toBTC();
result.lastItem = lastTx;
callback(null, result); callback(null, result);
//store in cache if needed
if(useCache) {
if(result.incomplete) //full summary needs to be calculated in background
self._cacheSummaryInBackground(address, lastTx, lastBlock, result);
else if (!_.isUndefined(lastCachedTx) && !_.isUndefined(lastTx)
&& lastTx != lastCachedTx && !self._cacheInstance.has(address)) //update cache if needed
self._storeCache(address, lastTx, lastBlock, result);
}
}); });
})
}
AddressService.prototype._cacheInstance = new Set();
AddressService.prototype._cacheSummaryInBackground = function(address, lastTx, lastBlock, result){
const self = this;
if(self._cacheInstance.has(address))
return;
self._cacheInstance.add(address);
const cache = {
balanceSat: result.balanceSat,
totalReceivedSat: result.totalReceivedSat,
totalSentSat: result.totalSentSat,
txApperances: result.txApperances,
unconfirmedBalanceSat: 0, //unconfirmed (mempool) values should not be cached
unconfirmedTxApperances: 0
};
const options = { queryMempool: false, after: lastTx, noTxList: true };
self._streamAddressSummary(address, options, function(err, tx) {
if(err)
return log.error(err);
if(tx) {
self._aggregateAddressSummaryResult(tx, address, cache, options);
if(tx.confirmations){
lastTx = tx.txid();
lastBlock = tx.blockhash;
}
}
}, function(err) {
if (err)
return log.error(err);
cache.balanceSat = parseInt(cache.balanceSat.toFixed());
cache.totalReceivedSat = parseInt(cache.totalReceivedSat.toFixed());
cache.totalSentSat = parseInt(cache.totalSentSat.toFixed());
cache.txApperances = parseInt(cache.txApperances.toFixed());
if(!_.isUndefined(lastTx))
self._storeCache(address, lastTx, lastBlock, cache);
self._cacheInstance.delete(address); //remove from running instance
});
}
AddressService.prototype._storeCache = function(address, lastCacheTx, lastCacheBlock, result, callback) {
const self = this;
var key = self._encoding.encodeAddressCacheKey(address);
var value = self._encoding.encodeAddressCacheValue(lastCacheTx, lastCacheBlock, result.balanceSat, result.totalReceivedSat, result.totalSentSat, result.txApperances)
if(!_.isFunction(callback)) //if callback is not passed, call a empty function
callback = () => null;
self._db.put(key, value, callback);
}
AddressService.prototype._loadCache = function(address, result, useCache, callback) {
const self = this;
if(!useCache) //skip if useCache is false (cases like 'after' and/or 'before' parameter is used by client)
return callback();
var key = self._encoding.encodeAddressCacheKey(address);
self._db.get(key, function(err, value) {
if (err) {
return callback(err);
}
if (!value) {
return callback();
}
var addressCache = self._encoding.decodeAddressCacheValue(value);
var lastCacheTx = addressCache.lastTx, lastCacheBlock = addressCache.lastBlock
self._block.getBlock(lastCacheBlock, function(err, block) {
if(err) {
return callback(err);
}
if (!block) { //block not found, probably removed in reorg.
//delete the existing cache and recalc values freshly
self._deleteCache(address, function() {
callback();
});
} else {
//values are in satoshis
result.balanceSat = addressCache.balance;
result.totalReceivedSat = addressCache.received;
result.totalSentSat = addressCache.sent;
result.txApperances = addressCache.txApperances;
callback(null, lastCacheTx);
}
})
});
}
AddressService.prototype._deleteCache = function(address, callback) {
const self = this;
var key = self._encoding.encodeAddressCacheKey(address);
if(!_.isFunction(callback)) //if callback is not passed, call a empty function
callback = () => null;
self._db.del(key, callback);
} }
AddressService.prototype._setOutputResults = function(tx, address, result) { AddressService.prototype._setOutputResults = function(tx, address, result) {
@ -672,9 +495,6 @@ AddressService.prototype._aggregateAddressSummaryResult = function (tx, address,
let input_val = self._getInputResults(tx, address); let input_val = self._getInputResults(tx, address);
//aggregate the result //aggregate the result
if(tx.confirmations) {
result.txApperances++; result.txApperances++;
result.totalReceivedSat += output_val; result.totalReceivedSat += output_val;
@ -683,7 +503,7 @@ AddressService.prototype._aggregateAddressSummaryResult = function (tx, address,
result.totalSentSat += input_val; result.totalSentSat += input_val;
result.balanceSat -= input_val; result.balanceSat -= input_val;
} else { if(!tx.confirmations){
result.unconfirmedTxApperances++; result.unconfirmedTxApperances++;
result.unconfirmedBalanceSat += output_val; result.unconfirmedBalanceSat += output_val;
result.unconfirmedBalanceSat -= input_val; result.unconfirmedBalanceSat -= input_val;
@ -700,7 +520,7 @@ AddressService.prototype._aggregateAddressSummaryResult = function (tx, address,
result.transactions.unshift(txid); //using unshift, so that recent tx (low confirmation) are at front result.transactions.unshift(txid); //using unshift, so that recent tx (low confirmation) are at front
if(result.transactions.length > MAX_TX_QUERY_LIMIT_SUMMARY) if(result.transactions.length > MAX_TX_QUERY_LIMIT)
result.transactions.pop(); //pop the oldest tx in list (when list limit is maxed out) result.transactions.pop(); //pop the oldest tx in list (when list limit is maxed out)
} }
@ -791,7 +611,7 @@ AddressService.prototype.getAddressUnspentOutputs = function(address, options, c
utxoStream.on('data', function(data) { utxoStream.on('data', function(data) {
if(results.length >= MAX_TX_QUERY_LIMIT_UTXO) { //Max array limit reached, end response if(results.length >= MAX_TX_QUERY_LIMIT) { //Max array limit reached, end response
utxoStream.emit('end'); utxoStream.emit('end');
return; return;
} }
@ -871,21 +691,29 @@ AddressService.prototype.stop = function(callback) {
AddressService.prototype._getTxidStream = function(address, options) { AddressService.prototype._getTxidStream = function(address, options) {
var criteria = {}; var start;
if(options.after) {
start = this._encoding.encodeAddressIndexKey(address, options.start, options.after, 0xffffffff, 1, 0xffffffff); //0xffffffff is for getting after the txid
} else {
start = this._encoding.encodeAddressIndexKey(address, options.start);
}
if(options.after) var endHeightBuf = new Buffer(4);
criteria.gt = this._encoding.encodeAddressIndexKey(address, options.start, options.after, 0xffffffff, 1, 0xffffffff); //0xffffffff is for getting after the txid endHeightBuf.writeUInt32BE(options.end);
else
criteria.gte = this._encoding.encodeAddressIndexKey(address, options.start);
if(options.before) var end = Buffer.concat([
criteria.lt = this._encoding.encodeAddressIndexKey(address, options.end, options.before); //get before the txid start.slice(0, address.length + 4),
else endHeightBuf,
criteria.lte = this._encoding.encodeAddressIndexKey(address, options.end, Array(65).join('f'), 0xffffffff, 1, 0xffffffff); new Buffer(new Array(83).join('f'), 'hex')
]);
var criteria = {
gte: start,
lte: end
//reverse: true // txids stream from low confirmations to high confirmations
};
//NOTE: commentted reverse to keep the order in asc when reading to preserve continuity when using `after` option
//reverse option can be used explictly when latest tx are required
if(options.reverse)
criteria.reverse = true;
// txid stream // txid stream
var txidStream = this._db.createKeyStream(criteria); var txidStream = this._db.createKeyStream(criteria);
@ -984,7 +812,7 @@ AddressService.prototype._getAddressTxidHistory = function(address, options, cal
txIdTransformStream._transform = function(chunk, enc, callback) { txIdTransformStream._transform = function(chunk, enc, callback) {
var txInfo = self._encoding.decodeAddressIndexKey(chunk); var txInfo = self._encoding.decodeAddressIndexKey(chunk);
if(results.length >= MAX_TX_QUERY_LIMIT_HISTORY) { //Max array limit reached, end response if(results.length >= MAX_TX_QUERY_LIMIT) { //Max array limit reached, end response
txIdTransformStream.emit('end'); txIdTransformStream.emit('end');
return; return;
} }
@ -1010,21 +838,13 @@ AddressService.prototype._streamAddressSummary = function(address, options, stre
options.start = options.start || 0; options.start = options.start || 0;
options.end = options.end || 0xffffffff; options.end = options.end || 0xffffffff;
//options.from = options.from || 0; //Deprecated, use `after` and `before` option //options.from = options.from || 0; //Deprecated, use `after` option
//options.to = options.to || 0xffffffff; //Deprecated, use `after` and `before` option //options.to = options.to || 0xffffffff; //Deprecated, use `after` option
if (_.isUndefined(options.queryMempool)) { if (_.isUndefined(options.queryMempool)) {
options.queryMempool = true; options.queryMempool = true;
} }
if (_.isUndefined(options.mempoolOnly)) {
options.mempoolOnly = false;
}
if (_.isUndefined(options.reverse)) {
options.reverse = false;
}
//declare the queue to process tx data //declare the queue to process tx data
var tmpTxList = {}; //store processed txid temporarily to ignore duplication var tmpTxList = {}; //store processed txid temporarily to ignore duplication
@ -1057,7 +877,7 @@ AddressService.prototype._streamAddressSummary = function(address, options, stre
self._transaction.getDetailedTransaction(id.txid, options, cb); self._transaction.getDetailedTransaction(id.txid, options, cb);
}, 1); }, 4);
//q.pause(); //pause and wait until queue is set (not needed) //q.pause(); //pause and wait until queue is set (not needed)
@ -1078,6 +898,8 @@ AddressService.prototype._streamAddressSummary = function(address, options, stre
if((err || options.flag_stop) && !q.killed){ if((err || options.flag_stop) && !q.killed){
console.debug("KILL", options.flag_stop)
q.kill(); q.kill();
q.killed = true; q.killed = true;
@ -1086,11 +908,10 @@ AddressService.prototype._streamAddressSummary = function(address, options, stre
} }
const waterfall_array = []; async.waterfall([
waterfall_array.push(
//Find start height if `after` option is passed //Find start height if `after` option is passed
function parse_after_id(next){ function(next){
if(_.isUndefined(options.after)) { if(_.isUndefined(options.after)) {
return next(); return next();
@ -1112,40 +933,10 @@ AddressService.prototype._streamAddressSummary = function(address, options, stre
}); });
}); },
waterfall_array.push( // stream the rest of the confirmed txids out of the address index
//Find end height if `before` option is passed function(next) {
function parse_before_id(next){
if(_.isUndefined(options.before)) {
return next();
}
self._transaction.getTransaction(options.before, options, function(err, tx) {
if(tx && tx.confirmations && tx.height <= options.end) {
options.end = tx.height;
} else {
delete options.before;
}
next();
});
});
// stream the confirmed txids out of the address index
function query_confirmed_txids(next) {
if (options.mempoolOnly) { //Option to query from mempool only (ie, unconfirmed txs only)
return next();
}
var txIdTransformStream = new Transform({ objectMode: true }); var txIdTransformStream = new Transform({ objectMode: true });
@ -1165,8 +956,10 @@ AddressService.prototype._streamAddressSummary = function(address, options, stre
txIdTransformStream._transform = function(chunk, enc, cb) { txIdTransformStream._transform = function(chunk, enc, cb) {
if(options.flag_stop)//stop data query if(options.flag_stop){//stop data query
console.debug("FLAG STOP:", options.flag_stop)
return txIdTransformStream.unpipe(); return txIdTransformStream.unpipe();
}
var txInfo = self._encoding.decodeAddressIndexKey(chunk); var txInfo = self._encoding.decodeAddressIndexKey(chunk);
q.push({ txid: txInfo.txid, height: txInfo.height }, chunkCallback); q.push({ txid: txInfo.txid, height: txInfo.height }, chunkCallback);
@ -1177,16 +970,20 @@ AddressService.prototype._streamAddressSummary = function(address, options, stre
var txidStream = self._getTxidStream(address, options); var txidStream = self._getTxidStream(address, options);
txidStream.pipe(txIdTransformStream); txidStream.pipe(txIdTransformStream);
} },
// query the mempool for relevant txs for this address // query the mempool for relevant txs for this address
function query_mempool_txids(next) { function(next) {
if (!options.queryMempool || !_.isUndefined(options.before)) { //if queryMempool=false or options.before is given a valid value, then do not query mempool if (!options.queryMempool) {
return next(); return next(null, []);
} }
self._mempool.getTxidsByAddress(address, 'both', function(err, mempoolTxids) { self._mempool.getTxidsByAddress(address, 'both', next);
},
// add the meta data such as input values, etc.
function(mempoolTxids, next) {
if (mempoolTxids.length <= 0) { if (mempoolTxids.length <= 0) {
return next(); return next();
@ -1194,31 +991,22 @@ AddressService.prototype._streamAddressSummary = function(address, options, stre
mempoolTxids.map(id => q.push(id, chunkCallback)); mempoolTxids.map(id => q.push(id, chunkCallback));
next(); next();
}); },
}
if(options.reverse){ //when queried txs in reverse key order, mempool first then confirmed
waterfall_array.push(query_mempool_txids);
waterfall_array.push(query_confirmed_txids);
} else { //when queried tx in key order, confirmed tx 1st, then mempool
waterfall_array.push(query_confirmed_txids);
waterfall_array.push(query_mempool_txids);
}
waterfall_array.push(
//wait for queue to complete //wait for queue to complete
function end_fall(next) { function(next) {
if(!q.started || q.idle()) //No tx in query (or) already finished querying console.debug("WAITING FOR QUEUE TO COMPLETE", q.started)
if(!q.started) //No tx in query
return next(); return next();
else else
q.drain = () => next(); q.drain = () => next();
}); }
async.waterfall(waterfall_array, callback); ], callback);
} }

View File

@ -724,13 +724,13 @@ BlockService.prototype._findLatestValidBlockHeader = function(callback) {
// if some joker mines a block using an orphan block as its prev block, then the effect of this will be // if some joker mines a block using an orphan block as its prev block, then the effect of this will be
// us detecting a reorg, but not actually reorging anything // us detecting a reorg, but not actually reorging anything
// FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error // FLOSight Error Correction from RanchiMall 17th May 2021. removed the unhandled assert and replaced by looging of error
if (!_.isUndefined(header)) { if (typeof header !== 'undefined') {
if (header == false) { if (header == false) {
log.error('Block Service: we could not locate any of our recent block hashes in the header service ' + 'index. Perhaps our header service sync\'ed to the wrong chain?'); log.error('Block Service: we could not locate any of our recent block hashes in the header service ' + 'index. Perhaps our header service sync\'ed to the wrong chain?');
} }
} }
// assert(header, 'Block Service: we could not locate any of our recent block hashes in the header service ' + 'index. Perhaps our header service sync\'ed to the wrong chain?'); // assert(header, 'Block Service: we could not locate any of our recent block hashes in the header service ' + 'index. Perhaps our header service sync\'ed to the wrong chain?');
if (!_.isUndefined(header.height)) { if (typeof header.height !== 'undefined') {
if (header.height > self._tip.height) { if (header.height > self._tip.height) {
log.error('Block Service: we found a common ancestor header whose ' + 'height was greater than our current tip. This should be impossible.'); log.error('Block Service: we found a common ancestor header whose ' + 'height was greater than our current tip. This should be impossible.');
} }

View File

@ -3,7 +3,6 @@
var util = require('util'); var util = require('util');
var fs = require('fs'); var fs = require('fs');
var async = require('async'); var async = require('async');
var _ = require('lodash');
var levelup = require('levelup'); var levelup = require('levelup');
var leveldown = require('leveldown'); var leveldown = require('leveldown');
var mkdirp = require('mkdirp'); var mkdirp = require('mkdirp');
@ -96,7 +95,7 @@ DB.prototype.get = function(key, options, callback) {
var cb = callback; var cb = callback;
var opts = options; var opts = options;
if (!_.isFunction(callback)) { if (typeof callback !== 'function') {
cb = options; cb = options;
opts = {}; opts = {};
} }
@ -151,21 +150,6 @@ DB.prototype.put = function(key, value, callback) {
this._store.put(key, value, callback); this._store.put(key, value, callback);
}; };
DB.prototype.del = function(key, callback) {
if (this._stopping) {
callback();
}
// FLOSight Error Correction from RanchiMall 20th May 2021. removed the unhandled assert and replaced by looging of error
if (Buffer.isBuffer(key) == false) {
log.error('key NOT a buffer as expected.');
}
// assert(Buffer.isBuffer(key), 'key NOT a buffer as expected.');
this._store.del(key, callback);
}
DB.prototype.batch = function(ops, callback) { DB.prototype.batch = function(ops, callback) {
if (this._stopping) { if (this._stopping) {

View File

@ -114,7 +114,7 @@ TransactionService.prototype.getTransaction = function(txid, options, callback)
var self = this; var self = this;
if (!_.isFunction(callback)) { if (typeof callback !== 'function') {
callback = options; callback = options;
} }

View File

@ -100,13 +100,15 @@ WebService.prototype.stop = function(callback) {
* all of the exposed HTTP routes. * all of the exposed HTTP routes.
*/ */
WebService.prototype.setupAllRoutes = function() { WebService.prototype.setupAllRoutes = function() {
for(var key in this.node.services) { const self = this;
for(var key in self.node.services) {
var subApp = new express(); var subApp = new express();
var service = this.node.services[key]; var service = self.node.services[key];
if(service.getRoutePrefix && service.setupRoutes) { if(service.getRoutePrefix && service.setupRoutes) {
this.app.use('/' + this.node.services[key].getRoutePrefix(), subApp); self.app.use('/' + self.node.services[key].getRoutePrefix(), subApp);
this.node.services[key].setupRoutes(subApp, express, express_ws); self.node.services[key].setupRoutes(subApp, express, a => express_ws(a, self.server));
} else { } else {
log.debug('No routes defined for: ' + key); log.debug('No routes defined for: ' + key);
} }

863
package-lock.json generated

File diff suppressed because it is too large Load Diff