locks. reject.

This commit is contained in:
Christopher Jeffrey 2016-03-30 22:36:52 -07:00
parent 17d2f1586b
commit b1d53adb6a
3 changed files with 112 additions and 84 deletions

View File

@ -266,6 +266,32 @@ Chain.prototype._preload = function _preload(callback) {
}; };
} }
function save(entry) {
if (save.locked)
return save.queue.push(entry);
save.locked = true;
self.db.save(entry, null, true, function(err) {
if (err)
return callback(err, 0);
save.locked = false;
if (save.queue.length === 0) {
if (save.ended)
return callback(null, height + 1);
return;
}
save(save.queue.shift());
});
}
save.locked = false;
save.queue = [];
save.ended = false;
this.db.getChainHeight(function(err, chainHeight) { this.db.getChainHeight(function(err, chainHeight) {
if (err) if (err)
return callback(err); return callback(err);
@ -288,7 +314,7 @@ Chain.prototype._preload = function _preload(callback) {
var start = Math.max(0, height - 2); var start = Math.max(0, height - 2);
self.reset(start, function(e) { self.reset(start, function(e) {
if (e) if (e)
throw e; return callback(e, 0);
return callback(err, start + 1); return callback(err, start + 1);
}); });
}); });
@ -319,7 +345,12 @@ Chain.prototype._preload = function _preload(callback) {
blocks.forEach(function(data) { blocks.forEach(function(data) {
var block, entry, start; var block, entry, start;
data = parseHeader(data); try {
data = parseHeader(data);
} catch (e) {
return callback(e, Math.max(0, height - 2));
}
data.height = height; data.height = height;
// Make sure the genesis block is correct. // Make sure the genesis block is correct.
@ -334,7 +365,7 @@ Chain.prototype._preload = function _preload(callback) {
stream.destroy(); stream.destroy();
return self.reset(start, function(err) { return self.reset(start, function(err) {
if (err) if (err)
throw err; return callback(err, 0);
return callback(new Error('Corrupt headers.'), start + 1); return callback(new Error('Corrupt headers.'), start + 1);
}); });
} }
@ -349,7 +380,7 @@ Chain.prototype._preload = function _preload(callback) {
stream.destroy(); stream.destroy();
return self.reset(start, function(err) { return self.reset(start, function(err) {
if (err) if (err)
throw err; return callback(err, 0);
return callback(new Error('Bad headers.'), start + 1); return callback(new Error('Bad headers.'), start + 1);
}); });
} }
@ -360,7 +391,7 @@ Chain.prototype._preload = function _preload(callback) {
if (entry.height <= chainHeight) if (entry.height <= chainHeight)
self.db.addCache(entry); self.db.addCache(entry);
else else
self.db.save(entry, null, true); save(entry);
if ((height + 1) % 50000 === 0) if ((height + 1) % 50000 === 0)
utils.debug('Received %d headers from electrum.org.', height + 1); utils.debug('Received %d headers from electrum.org.', height + 1);
@ -371,7 +402,9 @@ Chain.prototype._preload = function _preload(callback) {
}); });
stream.on('end', function() { stream.on('end', function() {
return callback(null, height + 1); save.ended = true;
if (!save.locked && save.queue.length === 0)
return callback(null, height + 1);
}); });
}); });
}; };
@ -909,8 +942,12 @@ Chain.prototype._setBestChain = function _setBestChain(entry, block, callback) {
// We don't have a genesis block yet. // We don't have a genesis block yet.
if (!this.tip) { if (!this.tip) {
if (entry.hash !== network.genesis.hash) if (entry.hash !== network.genesis.hash) {
return utils.asyncify(callback)(new Error('Bad genesis block.')); return utils.asyncify(callback)(new VerifyError(block,
'invalid',
'bad-genblk',
100));
}
return done(); return done();
} }
@ -946,13 +983,11 @@ Chain.prototype.reset = function reset(height, callback, force) {
if (!unlock) if (!unlock)
return; return;
callback = utils.ensure(callback); callback = utils.wrap(callback, unlock);
this.db.reset(height, function(err, result) { this.db.reset(height, function(err, result) {
if (err) { if (err)
unlock();
return callback(err); return callback(err);
}
// Reset the orphan map completely. There may // Reset the orphan map completely. There may
// have been some orphans on a forked chain we // have been some orphans on a forked chain we
@ -960,7 +995,6 @@ Chain.prototype.reset = function reset(height, callback, force) {
self.purgeOrphans(); self.purgeOrphans();
self.purgePending(); self.purgePending();
unlock();
callback(null, result); callback(null, result);
}); });
}; };
@ -972,25 +1006,16 @@ Chain.prototype.resetTime = function resetTime(ts, callback, force) {
if (!unlock) if (!unlock)
return; return;
callback = utils.ensure(callback); callback = utils.wrap(callback, unlock);
this.byTime(ts, function(err, entry) { this.byTime(ts, function(err, entry) {
if (err) { if (err)
unlock(); return callback(err);
callback(err);
return;
}
if (!entry) { if (!entry)
unlock(); return callback();
callback();
return;
}
self.reset(entry.height, function(err) { self.reset(entry.height, callback, true);
unlock();
callback(err);
}, true);
}, true); }, true);
}; };
@ -1009,6 +1034,8 @@ Chain.prototype.add = function add(block, callback, force) {
if (!unlock) if (!unlock)
return; return;
callback = utils.wrap(callback, unlock);
(function next(block, initial) { (function next(block, initial) {
var hash = block.hash('hex'); var hash = block.hash('hex');
var prevHash = block.prevBlock; var prevHash = block.prevBlock;
@ -1240,13 +1267,15 @@ Chain.prototype.add = function add(block, callback, force) {
// Emit our block (and potentially resolved // Emit our block (and potentially resolved
// orphan) only if it is on the main chain. // orphan) only if it is on the main chain.
if (mainChain) if (mainChain) {
self.emit('block', block, entry); self.emit('block', block, entry);
else if (!initial)
self.emit('resolved', block, entry);
} else {
self.emit('competitor', block, entry); self.emit('competitor', block, entry);
if (!initial)
if (!initial) self.emit('competitor resolved', block, entry);
self.emit('resolved', block, entry); }
// No orphan chain. // No orphan chain.
if (!self.orphan.map[hash]) if (!self.orphan.map[hash])
@ -1285,8 +1314,6 @@ Chain.prototype.add = function add(block, callback, force) {
if (self.isFull()) if (self.isFull())
self.emit('full'); self.emit('full');
unlock();
if (err) if (err)
callback(err); callback(err);
else else
@ -1368,31 +1395,23 @@ Chain.prototype.byTime = function byTime(ts, callback, force) {
var end = this.height; var end = this.height;
var pos, delta; var pos, delta;
var unlock = this._lock(byTime, [ts, callback], force); // var unlock = this._lock(byTime, [ts, callback], force);
if (!unlock) // if (!unlock)
return; // return;
// callback = utils.wrap(callback, unlock);
callback = utils.asyncify(callback);
function done(err, result) { function done(err, result) {
if (err) { if (err)
unlock();
return callback(err); return callback(err);
}
if (result) { if (result)
unlock();
return callback(null, result); return callback(null, result);
}
self.db.get(start, function(err, entry) { self.db.get(start, callback);
unlock();
callback(err, entry);
});
} }
if (ts >= this.tip.ts) if (ts >= this.tip.ts)
return done(null, this.tip); return utils.asyncify(done)(null, this.tip);
// Do a binary search for a block // Do a binary search for a block
// mined within an hour of the // mined within an hour of the
@ -1501,29 +1520,25 @@ Chain.prototype.getProgress = function getProgress() {
Chain.prototype.getHashRange = function getHashRange(start, end, callback, force) { Chain.prototype.getHashRange = function getHashRange(start, end, callback, force) {
var self = this; var self = this;
var unlock = this._lock(getHashRange, [start, end, callback], force); // var unlock = this._lock(getHashRange, [start, end, callback], force);
if (!unlock) // if (!unlock)
return; // return;
// callback = utils.wrap(callback, unlock);
function done(err, result) {
unlock();
callback(err, result);
}
this.byTime(start, function(err, start) { this.byTime(start, function(err, start) {
if (err) if (err)
return done(err); return callback(err);
self.byTime(end, function(err, end) { self.byTime(end, function(err, end) {
var hashes; var hashes;
if (err) if (err)
return done(err); return callback(err);
hashes = []; hashes = [];
if (!start || !end) if (!start || !end)
return done(null, hashes); return callback(null, hashes);
utils.forRange(start.height, end.height + 1, function(i, next) { utils.forRange(start.height, end.height + 1, function(i, next) {
self.db.get(i, function(err, entry) { self.db.get(i, function(err, entry) {
@ -1539,8 +1554,8 @@ Chain.prototype.getHashRange = function getHashRange(start, end, callback, force
}); });
}, function(err) { }, function(err) {
if (err) if (err)
return done(err); return callback(err);
return done(null, hashes); return callback(null, hashes);
}); });
}, true); }, true);
}, true); }, true);
@ -1556,6 +1571,7 @@ Chain.prototype.getLocator = function getLocator(start, callback, force) {
var unlock = this._lock(getLocator, [start, callback], force); var unlock = this._lock(getLocator, [start, callback], force);
if (!unlock) if (!unlock)
return; return;
callback = utils.wrap(callback, unlock);
if (start) { if (start) {
if (Buffer.isBuffer(start)) if (Buffer.isBuffer(start))
@ -1589,10 +1605,8 @@ Chain.prototype.getLocator = function getLocator(start, callback, force) {
} }
return getTop(function(err, top) { return getTop(function(err, top) {
if (err) { if (err)
unlock();
return callback(err); return callback(err);
}
i = top; i = top;
for (;;) { for (;;) {
@ -1622,7 +1636,6 @@ Chain.prototype.getLocator = function getLocator(start, callback, force) {
next(); next();
}); });
}, function(err) { }, function(err) {
unlock();
if (err) if (err)
return callback(err); return callback(err);
return callback(null, hashes); return callback(null, hashes);
@ -1952,11 +1965,10 @@ Chain.prototype.isSegwitActive = function isSegwitActive(callback) {
if (!this.tip) if (!this.tip)
return utils.asyncify(callback)(null, false); return utils.asyncify(callback)(null, false);
unlock = this._lock(isSegwitActive, [callback]); // unlock = this._lock(isSegwitActive, [callback]);
if (!unlock) // if (!unlock)
return; // return;
// callback = utils.wrap(callback, unlock);
callback = utils.wrap(callback, unlock);
if (network.type === 'segnet4') { if (network.type === 'segnet4') {
return this.tip.getPrevious(function(err, prev) { return this.tip.getPrevious(function(err, prev) {
@ -2090,6 +2102,12 @@ Chain.prototype.evalLocks = function evalLocks(entry, minHeight, minTime, callba
Chain.prototype.checkLocks = function checkLocks(tx, flags, entry, callback) { Chain.prototype.checkLocks = function checkLocks(tx, flags, entry, callback) {
var self = this; var self = this;
// var unlock = this._lock(checkLocks, [tx, flags, entry, callback], force);
// if (!unlock)
// return;
// callback = utils.wrap(callback, unlock);
this.getLocks(tx, flags, entry, function(err, minHeight, minTime) { this.getLocks(tx, flags, entry, function(err, minHeight, minTime) {
if (err) if (err)
return callback(err); return callback(err);

View File

@ -140,6 +140,7 @@ Peer.prototype._init = function init() {
this.parser.on('error', function(err) { this.parser.on('error', function(err) {
utils.debug(err.stack + ''); utils.debug(err.stack + '');
peer.sendReject(null, 'malformed', 'error parsing message', 100);
self._error(err); self._error(err);
// Something is wrong here. // Something is wrong here.
// Ignore this peer. // Ignore this peer.

View File

@ -1925,19 +1925,28 @@ Pool.prototype.isMisbehaving = function isMisbehaving(host) {
}; };
Pool.prototype.reject = function reject(peer, obj, code, reason, score) { Pool.prototype.reject = function reject(peer, obj, code, reason, score) {
if (obj) {
utils.debug('Rejecting %s %s from %s: ccode=%s reason=%s',
obj.type, obj.hash('hex'), peer.host, code, reason);
peer.reject({
ccode: code,
reason: reason,
data: obj.hash()
});
} else {
utils.debug('Rejecting packet from %s: ccode=%s reason=%s',
peer.host, code, reason);
peer.reject({
ccode: code,
reason: reason,
data: null
});
}
if (score != null) if (score != null)
peer.setMisbehavior(score); peer.setMisbehavior(score);
utils.debug('Rejecting %s %s: ccode=%s reason=%s',
obj.type, obj.hash('hex'), code, reason);
peer.reject({
ccode: code,
reason: reason,
data: obj.hash()
});
return false;
}; };
/** /**