Added a utxo cache.
This commit is contained in:
parent
95d5441031
commit
bdea9e8517
154
lib/addresses.js
154
lib/addresses.js
@ -6,6 +6,7 @@ var async = require('async');
|
||||
var TxController = require('./transactions');
|
||||
var Common = require('./common');
|
||||
var _ = require('lodash');
|
||||
var LRU = require('lru-cache');
|
||||
|
||||
function AddressController(node) {
|
||||
this.node = node;
|
||||
@ -14,6 +15,14 @@ function AddressController(node) {
|
||||
this.txController = new TxController(node);
|
||||
this.common = new Common({log: this.node.log});
|
||||
this._block = this.node.services.block;
|
||||
this._utxoCache = new LRU({
|
||||
max: 250,
|
||||
maxAge: 1000 * 10
|
||||
});
|
||||
// limit the size of the request to about 100,000 bytes
|
||||
// we'll use 34 bytes as the size of each address.
|
||||
this._maxAddresses = Math.floor(100000/34);
|
||||
|
||||
}
|
||||
|
||||
AddressController.prototype.show = function(req, res) {
|
||||
@ -142,73 +151,25 @@ AddressController.prototype.check = function(addresses) {
|
||||
AddressController.prototype.utxo = function(req, res) {
|
||||
var self = this;
|
||||
|
||||
var cachedUtxos = this._utxoCache.get(req.addr);
|
||||
|
||||
if (cachedUtxos) {
|
||||
return res.jsonp(cachedUtxos);
|
||||
}
|
||||
|
||||
this._address.getAddressUnspentOutputs(req.addr, {}, function(err, utxos) {
|
||||
var results;
|
||||
if(err) {
|
||||
return self.common.handleErrors(err, res);
|
||||
} else if (!utxos.length) {
|
||||
return res.jsonp([]);
|
||||
results = [];
|
||||
}
|
||||
res.jsonp(utxos.map(self.transformUtxo.bind(self)));
|
||||
results = utxos.map(self.transformUtxo.bind(self));
|
||||
self._utxoCache.set(req.addr, results);
|
||||
res.jsonp(results);
|
||||
});
|
||||
};
|
||||
|
||||
// this call could take a while to run depending on what addresses are used
|
||||
// considering memory constraints, we will streaming out the results for addresses
|
||||
// not necessarily in the order we received them
|
||||
AddressController.prototype.multiutxo = function(req, res) {
|
||||
var self = this;
|
||||
|
||||
var addresses;
|
||||
|
||||
if (_.isArray(req.addrs)) {
|
||||
addresses = _.uniq(req.addrs);
|
||||
} else {
|
||||
addresses = req.addrs.split(',');
|
||||
}
|
||||
|
||||
var addressesLeft = addresses.length;
|
||||
var startedWriting = false;
|
||||
res.write('[');
|
||||
|
||||
var sep = ',';
|
||||
|
||||
async.eachLimit(addresses, 4, function(addr, next) {
|
||||
|
||||
self._address.getAddressUnspentOutputs(addr, {}, function(err, utxos) {
|
||||
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
if (addressesLeft-- > 0 && utxos.length > 0 && startedWriting) {
|
||||
res.write(sep);
|
||||
}
|
||||
|
||||
for(var i = 0; i < utxos.length; i++) {
|
||||
startedWriting = true;
|
||||
if (utxos.length - 1 === i) {
|
||||
sep = '';
|
||||
}
|
||||
res.write(JSON.stringify(self.transformUtxo(utxos[i])) + sep);
|
||||
}
|
||||
|
||||
sep = ',';
|
||||
next();
|
||||
|
||||
});
|
||||
|
||||
}, function(err) {
|
||||
|
||||
if (err) {
|
||||
return self.common.handleErrors(err, res);
|
||||
}
|
||||
|
||||
res.write(']');
|
||||
res.end();
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
AddressController.prototype.transformUtxo = function(utxoArg) {
|
||||
var utxo = {
|
||||
address: utxoArg.address,
|
||||
@ -238,6 +199,81 @@ AddressController.prototype._getTransformOptions = function(req) {
|
||||
};
|
||||
};
|
||||
|
||||
// this call could take a while to run depending on what addresses are used
|
||||
// considering memory constraints, we will streaming out the results for addresses
|
||||
// not necessarily in the order we received them
|
||||
AddressController.prototype.multiutxo = function(req, res) {
|
||||
|
||||
var self = this;
|
||||
|
||||
var addresses;
|
||||
|
||||
if (_.isArray(req.addrs)) {
|
||||
addresses = _.uniq(req.addrs);
|
||||
} else {
|
||||
addresses = _.compact(req.addrs.split(','));
|
||||
}
|
||||
|
||||
var cacheKey = addresses.join('');
|
||||
|
||||
if (addresses.length > this._maxAddresses) {
|
||||
return self.common.handleErrors(new Error('Too many addresses.'), res);
|
||||
}
|
||||
|
||||
var cachedUtxos = this._utxoCache.get(cacheKey);
|
||||
|
||||
if (cachedUtxos) {
|
||||
return res.jsonp(cachedUtxos);
|
||||
}
|
||||
|
||||
var addressesLeft = addresses.length;
|
||||
var startedWriting = false;
|
||||
var cache = [];
|
||||
|
||||
res.write('[');
|
||||
|
||||
var sep = ',';
|
||||
|
||||
async.eachLimit(addresses, 4, function(addr, next) {
|
||||
|
||||
self._address.getAddressUnspentOutputs(addr, {}, function(err, utxos) {
|
||||
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
if (addressesLeft-- > 0 && utxos.length > 0 && startedWriting) {
|
||||
res.write(sep);
|
||||
}
|
||||
|
||||
for(var i = 0; i < utxos.length; i++) {
|
||||
startedWriting = true;
|
||||
if (utxos.length - 1 === i) {
|
||||
sep = '';
|
||||
}
|
||||
cache.push(utxos[i]);
|
||||
res.write(JSON.stringify(self.transformUtxo(utxos[i])) + sep);
|
||||
}
|
||||
|
||||
sep = ',';
|
||||
next();
|
||||
|
||||
});
|
||||
|
||||
}, function(err) {
|
||||
|
||||
if (err) {
|
||||
return self.common.handleErrors(err, res);
|
||||
}
|
||||
|
||||
self._utxoCache.set(cacheKey, cache);
|
||||
|
||||
res.write(']');
|
||||
res.end();
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
AddressController.prototype.multitxs = function(req, res) {
|
||||
var self = this;
|
||||
|
||||
|
||||
30
package-lock.json
generated
30
package-lock.json
generated
@ -1063,24 +1063,12 @@
|
||||
"integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4="
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz",
|
||||
"integrity": "sha1-E0OVXtry432bnn7nJB4nxLn7cr4=",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz",
|
||||
"integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==",
|
||||
"requires": {
|
||||
"pseudomap": "1.0.2",
|
||||
"yallist": "2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||
},
|
||||
"yallist": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.0.0.tgz",
|
||||
"integrity": "sha1-MGxUODXwnuGkyyO3vOmrNByRzdQ="
|
||||
}
|
||||
"yallist": "2.1.2"
|
||||
}
|
||||
},
|
||||
"mime-db": {
|
||||
@ -1542,6 +1530,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||
},
|
||||
"pump": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-1.0.2.tgz",
|
||||
@ -2417,6 +2410,11 @@
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
|
||||
"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
|
||||
},
|
||||
"yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
|
||||
},
|
||||
"yeast": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
"body-parser": "^1.13.3",
|
||||
"compression": "^1.6.1",
|
||||
"lodash": "^2.4.1",
|
||||
"lru-cache": "^4.0.1",
|
||||
"lru-cache": "^4.1.1",
|
||||
"morgan": "^1.7.0",
|
||||
"request": "^2.64.0"
|
||||
},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user