net: refactor reject msg. broadcast orphans.

This commit is contained in:
Christopher Jeffrey 2016-12-17 13:50:45 -08:00
parent 2d831ca5bd
commit 514e735a96
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
5 changed files with 77 additions and 34 deletions

View File

@ -1894,6 +1894,29 @@ RejectPacket.fromOptions = function fromOptions(options) {
return new RejectPacket().fromOptions(options); return new RejectPacket().fromOptions(options);
}; };
/**
* Get uint256le hash if present.
* @returns {Hash}
*/
RejectPacket.prototype.rhash = function rhash() {
return this.hash ? util.revHex(this.hash) : null;
};
/**
* Get symbolic code.
* @returns {String}
*/
RejectPacket.prototype.getCode = function getCode() {
var code = constants.rejectByVal[this.code];
if (!code)
return this.code + '';
return code.toLowerCase();
};
/** /**
* Get serialization size. * Get serialization size.
* @returns {Number} * @returns {Number}

View File

@ -183,8 +183,8 @@ Peer.prototype._init = function init() {
try { try {
yield self.handlePacket(packet); yield self.handlePacket(packet);
} catch (e) { } catch (e) {
self.destroy();
self.error(e); self.error(e);
self.destroy();
} }
})); }));
@ -195,8 +195,8 @@ Peer.prototype._init = function init() {
if (this.bip151) { if (this.bip151) {
this.bip151.on('error', function(err) { this.bip151.on('error', function(err) {
self.reject(null, 'malformed', 'error parsing message', 10);
self.error(err); self.error(err);
self.reject(null, 'malformed', 'error parsing message', 10);
}); });
this.bip151.on('rekey', function() { this.bip151.on('rekey', function() {
self.logger.debug('Rekeying with peer (%s).', self.hostname); self.logger.debug('Rekeying with peer (%s).', self.hostname);
@ -231,8 +231,8 @@ Peer.prototype.bind = function bind(socket) {
this.socket = socket; this.socket = socket;
this.socket.once('error', function(err) { this.socket.once('error', function(err) {
self.destroy();
self.error(err); self.error(err);
self.destroy();
switch (err.code) { switch (err.code) {
case 'ECONNREFUSED': case 'ECONNREFUSED':
@ -250,10 +250,8 @@ Peer.prototype.bind = function bind(socket) {
}); });
this.socket.once('close', function() { this.socket.once('close', function() {
if (self.destroyed)
return;
self.destroy();
self.error('socket hangup'); self.error('socket hangup');
self.destroy();
}); });
this.socket.on('drain', function() { this.socket.on('drain', function() {
@ -332,7 +330,7 @@ Peer.prototype.open = co(function* open() {
yield this.finalize(); yield this.finalize();
if (this.destroyed) if (this.destroyed)
throw new Error('Peer was destroyed.'); throw new Error('Peer was destroyed before handshake.');
// Finally we can let the pool know // Finally we can let the pool know
// that this peer is ready to go. // that this peer is ready to go.
@ -348,8 +346,8 @@ Peer.prototype.tryOpen = co(function* tryOpen() {
try { try {
yield this.open(); yield this.open();
} catch (e) { } catch (e) {
this.destroy();
this.error(e); this.error(e);
this.destroy();
} }
}); });
@ -917,8 +915,8 @@ Peer.prototype.write = function write(data) {
Peer.prototype.needsDrain = function needsDrain(size) { Peer.prototype.needsDrain = function needsDrain(size) {
if (this.maybeStall()) { if (this.maybeStall()) {
this.destroy();
this.error('Peer stalled (drain).'); this.error('Peer stalled (drain).');
this.destroy();
return; return;
} }
@ -930,8 +928,8 @@ Peer.prototype.needsDrain = function needsDrain(size) {
'Peer is not reading: %dmb buffered (%s).', 'Peer is not reading: %dmb buffered (%s).',
util.mb(this.drainSize), util.mb(this.drainSize),
this.hostname); this.hostname);
this.destroy();
this.error('Peer stalled (drain).'); this.error('Peer stalled (drain).');
this.destroy();
} }
}; };
@ -948,8 +946,8 @@ Peer.prototype.maybeStall = function maybeStall() {
return false; return false;
this.drainSize = 0; this.drainSize = 0;
this.destroy();
this.error('Peer stalled.'); this.error('Peer stalled.');
this.destroy();
return true; return true;
}; };
@ -998,6 +996,9 @@ Peer.prototype.sendRaw = function sendRaw(cmd, body, checksum) {
Peer.prototype.error = function error(err) { Peer.prototype.error = function error(err) {
var i, args, msg; var i, args, msg;
if (this.destroyed)
return;
if (typeof err === 'string') { if (typeof err === 'string') {
args = new Array(arguments.length); args = new Array(arguments.length);

View File

@ -1385,23 +1385,13 @@ Pool.prototype.handleTXInv = function handleTXInv(txs, peer) {
*/ */
Pool.prototype.handleReject = function handleReject(reject, peer) { Pool.prototype.handleReject = function handleReject(reject, peer) {
var data, code;
if (reject.hash)
data = util.revHex(reject.hash);
code = constants.rejectByVal[reject.code];
if (code)
code = code.toLowerCase();
this.logger.warning( this.logger.warning(
'Received reject (%s): msg=%s code=%s reason=%s data=%s.', 'Received reject (%s): msg=%s code=%s reason=%s hash=%s.',
peer.hostname, peer.hostname,
reject.message, reject.message,
code || reject.code, reject.getCode(),
reject.reason, reject.reason,
data || null); reject.rhash());
this.emit('reject', reject, peer); this.emit('reject', reject, peer);
}; };

View File

@ -303,9 +303,13 @@ FullNode.prototype.scan = function scan(start, filter, iter) {
* @returns {Promise} * @returns {Promise}
*/ */
FullNode.prototype.broadcast = function broadcast(item) { FullNode.prototype.broadcast = co(function* broadcast(item) {
return this.pool.broadcast(item); try {
}; yield this.pool.broadcast(item);
} catch (e) {
this.emit('error', e);
}
});
/** /**
* Verify a transaction, add it to the mempool, and broadcast. * Verify a transaction, add it to the mempool, and broadcast.
@ -317,19 +321,40 @@ FullNode.prototype.broadcast = function broadcast(item) {
*/ */
FullNode.prototype.sendTX = co(function* sendTX(tx) { FullNode.prototype.sendTX = co(function* sendTX(tx) {
var missing;
try { try {
yield this.mempool.addTX(tx); missing = yield this.mempool.addTX(tx);
} catch (err) { } catch (err) {
if (err.type === 'VerifyError') { if (err.type === 'VerifyError' && err.score === 0) {
this._error(err); this._error(err);
this.logger.warning('Verification failed for tx: %s.', tx.txid()); this.logger.warning('Verification failed for tx: %s.', tx.txid());
this.logger.warning('Attempting to broadcast anyway...'); this.logger.warning('Attempting to broadcast anyway...');
yield this.pool.broadcast(tx); this.broadcast(tx);
return; return;
} }
throw err; throw err;
} }
if (missing) {
this.logger.warning('TX was orphaned in mempool: %s.', tx.txid());
// Avoid getting dos'd by bitcoind for now.
// See: https://github.com/bitcoin/bitcoin/issues/9182
// Once this fix is widely deployed, we can remove this.
if (tx.hasWitness()) {
this.logger.warning('Not broadcasting for now to avoid bitcoind DoS.');
return;
}
this.logger.warning('Attempting to broadcast anyway...');
this.broadcast(tx);
return;
}
// We need to announce by hand if
// we're running in selfish mode.
if (this.options.selfish) if (this.options.selfish)
this.pool.announceTX(tx); this.pool.announceTX(tx);
}); });

View File

@ -282,9 +282,13 @@ SPVNode.prototype.watchBlock = co(function* watchBlock(entry, block) {
* @returns {Promise} * @returns {Promise}
*/ */
SPVNode.prototype.broadcast = function broadcast(item) { SPVNode.prototype.broadcast = co(function* broadcast(item) {
return this.pool.broadcast(item); try {
}; yield this.pool.broadcast(item);
} catch (e) {
this.emit('error', e);
}
});
/** /**
* Broadcast a transaction (note that this will _not_ be verified * Broadcast a transaction (note that this will _not_ be verified
@ -295,7 +299,7 @@ SPVNode.prototype.broadcast = function broadcast(item) {
*/ */
SPVNode.prototype.sendTX = function sendTX(tx) { SPVNode.prototype.sendTX = function sendTX(tx) {
return this.pool.broadcast(tx); return this.broadcast(tx);
}; };
/** /**