net: refactor reject msg. broadcast orphans.
This commit is contained in:
parent
2d831ca5bd
commit
514e735a96
@ -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}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user