refactor pool.search.

This commit is contained in:
Christopher Jeffrey 2016-02-19 22:02:52 -08:00
parent 48d7b95d61
commit 3c29e20df2

View File

@ -1363,27 +1363,15 @@ Pool.prototype.searchWallet = function(w, h) {
}); });
}; };
Pool.prototype.search = function search(id, range, e) { Pool.prototype.search = function search(id, range, callback) {
var self = this; var self = this;
var hashes, pending, listener, timeout, done, total, cb;
assert(!this.loading); assert(!this.loading);
if (!this.options.spv) if (!this.options.spv)
return; return;
if (typeof e === 'function') { if (range == null) {
cb = e;
e = null;
}
e = e || new EventEmitter();
// Optional id argument
if ((id !== null
&& typeof id === 'object'
&& !utils.isBuffer(id))
|| typeof id === 'number') {
range = id; range = id;
id = null; id = null;
} }
@ -1398,63 +1386,42 @@ Pool.prototype.search = function search(id, range, e) {
else else
range = { start: 0, end: 0 }; range = { start: 0, end: 0 };
// Last 5 days by default, this covers 1000 blocks that we have in the
// chain by default
if (!range.end) if (!range.end)
range.end = utils.now(); range.end = utils.now();
if (!range.start) if (!range.start)
range.start = utils.now() - 432000; range.start = utils.now() - 432000;
if (cb) {
e.once('end', function(empty) {
if (empty)
return cb(new Error('Not found.'), false);
return cb(null, true);
});
}
if (id) if (id)
this.watch(id); this.watch(id);
done = function(empty) { callback = utils.asyncify(callback);
e.emit('end', empty);
clearInterval(timeout); function done(err, completed) {
self.removeListener('block', listener); self.removeListener('block', onBlock);
if (id) if (id)
self.unwatch(id); self.unwatch(id);
}; callback(err, completed);
}
this.on('block', listener = function(block) { function onBlock(block) {
if (block.ts >= range.end) if (block.ts >= range.end)
done(); done(null, true);
}); }
// Estimated number of blocks in time range this.on('block', onBlock);
total = (range.end - range.start) / network.powTargetSpacing | 0;
if (total === 0)
total = 1;
// 500 blocks every 3 seconds
total = (total / 500 | 0) * 3;
// Add half the total time and convert to ms
total = (total + Math.ceil(total / 2)) * 1000;
timeout = setTimeout(done.bind(null, true), total);
if (range.start < this.chain.tip.ts) { if (range.start < this.chain.tip.ts) {
this.chain.resetTimeAsync(range.start, function(err) { this.chain.resetTimeAsync(range.start, function(err) {
if (err) if (err)
throw err; return done(err);
self.stopSync(); self.stopSync();
self.startSync(); self.startSync();
}); });
} else {
done(null, false);
} }
return e;
}; };
Pool.prototype.getData = function getData(peer, type, hash, options, cb) { Pool.prototype.getData = function getData(peer, type, hash, options, cb) {
@ -1597,10 +1564,10 @@ Pool.prototype.sendBlock = function sendBlock(block) {
Pool.prototype.getTX = function getTX(hash, range, cb) { Pool.prototype.getTX = function getTX(hash, range, cb) {
var self = this; var self = this;
var cbs, tx, finished, req, delta; var cbs, tx, found, delta;
if (!this.peers.load) if (!this.peers.load)
return setTimeout(this.getBlock.bind(this, hash, cb), 1000); return setTimeout(this.getTX.bind(this, hash, cb), 1000);
if (!this.options.spv) if (!this.options.spv)
return cb(new Error('Cannot get tx with full node')); return cb(new Error('Cannot get tx with full node'));
@ -1621,9 +1588,9 @@ Pool.prototype.getTX = function getTX(hash, range, cb) {
// Add request without queueing it to get notification at the time of load // Add request without queueing it to get notification at the time of load
tx = null; tx = null;
finished = false; found = false;
req = this.getData(this.peers.load, 'tx', hash, { noQueue: true }, function(t) { this.getData(this.peers.load, 'tx', hash, { noQueue: true }, function(t) {
finished = true; found = true;
tx = t; tx = t;
}); });
@ -1636,20 +1603,23 @@ Pool.prototype.getTX = function getTX(hash, range, cb) {
else else
range = { start: utils.now() - delta, end: 0 }; range = { start: utils.now() - delta, end: 0 };
function doSearch() { function done(err, tx, range) {
var e = self.search(hash, range); delete self.validate.map[hash];
e.on('end', function(empty) { cbs.forEach(function(cb) {
if (finished) { cb(err, tx, range);
delete self.validate.map[hash]; });
cbs.forEach(function(cb) { }
cb(null, tx, range);
});
return;
}
// Tried everything, but still no matches (function next() {
if (empty) self.search(hash, range, function(err, completed) {
return cb(new Error('Not found.')); if (err)
return done(err);
if (found)
return done(null, tx, range);
if (!completed)
return done();
// Not found yet, continue scanning // Not found yet, continue scanning
range.end = range.start; range.end = range.start;
@ -1657,20 +1627,19 @@ Pool.prototype.getTX = function getTX(hash, range, cb) {
if (range.start < 0) if (range.start < 0)
range.start = 0; range.start = 0;
doSearch(); next();
}); });
} })();
doSearch();
}; };
Pool.prototype.sendTX = function sendTX(tx) { Pool.prototype.sendTX = function sendTX(tx) {
var flags = constants.flags.STANDARD_VERIFY_FLAGS;
// This is to avoid getting banned by // This is to avoid getting banned by
// bitcoind nodes. Possibly check // bitcoind nodes. Possibly check
// sigops. Call isStandard and/or // sigops. Call isStandard and/or
// isStandardInputs as well. // isStandardInputs as well.
if (tx.hasPrevout()) { if (tx.hasPrevout()) {
if (!tx.verify(null, true)) { if (!tx.verify(null, true, flags)) {
utils.debug( utils.debug(
'Could not relay TX (%s). It does not verify.', 'Could not relay TX (%s). It does not verify.',
tx.rhash); tx.rhash);