peer: refactor version packet handling.
This commit is contained in:
parent
212a69697e
commit
db49f44c8a
@ -532,10 +532,10 @@ RPC.prototype.getpeerinfo = co(function* getpeerinfo(args) {
|
|||||||
? (peer.lastPong - peer.lastPing) / 1000
|
? (peer.lastPong - peer.lastPing) / 1000
|
||||||
: -1,
|
: -1,
|
||||||
minping: peer.minPing !== -1 ? peer.minPing / 1000 : -1,
|
minping: peer.minPing !== -1 ? peer.minPing / 1000 : -1,
|
||||||
version: peer.version ? peer.version.version : 0,
|
version: peer.version,
|
||||||
subver: peer.version ? peer.version.agent : '',
|
subver: peer.agent,
|
||||||
inbound: !peer.outbound,
|
inbound: !peer.outbound,
|
||||||
startingheight: peer.version ? peer.version.height : -1,
|
startingheight: peer.height,
|
||||||
banscore: peer.banScore,
|
banscore: peer.banScore,
|
||||||
inflight: peer.requestMap.keys().map(util.revHex),
|
inflight: peer.requestMap.keys().map(util.revHex),
|
||||||
whitelisted: false
|
whitelisted: false
|
||||||
|
|||||||
@ -333,15 +333,10 @@ BIP150.prototype.findAuthorized = function findAuthorized(hash) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
BIP150.prototype.destroy = function destroy() {
|
BIP150.prototype.destroy = function destroy() {
|
||||||
if (this.timeout != null) {
|
if (!this.job)
|
||||||
clearTimeout(this.timeout);
|
return;
|
||||||
this.timeout = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.onAuth) {
|
this.reject(new Error('BIP150 stream was destroyed.'));
|
||||||
this.removeListener('auth', this.onAuth);
|
|
||||||
this.onAuth = null;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -547,15 +547,10 @@ BIP151.prototype._wait = function wait(timeout, resolve, reject) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
BIP151.prototype.destroy = function destroy() {
|
BIP151.prototype.destroy = function destroy() {
|
||||||
if (this.timeout != null) {
|
if (!this.job)
|
||||||
clearTimeout(this.timeout);
|
return;
|
||||||
this.timeout = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.onShake) {
|
this.reject(new Error('BIP151 stream was destroyed.'));
|
||||||
this.removeListener('handshake', this.onShake);
|
|
||||||
this.onShake = null;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -25,6 +25,38 @@ exports.PROTOCOL_VERSION = 70015;
|
|||||||
|
|
||||||
exports.MIN_VERSION = 70001;
|
exports.MIN_VERSION = 70001;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimum version for getheaders.
|
||||||
|
* @const {Number}
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.HEADERS_VERSION = 31800;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimum version for bip37.
|
||||||
|
* @const {Number}
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.BLOOM_VERSION = 70011;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimum version for bip152.
|
||||||
|
* @const {Number}
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.SENDHEADERS_VERSION = 7012;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimum version for bip152.
|
||||||
|
* @const {Number}
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.COMPACT_VERSION = 70014;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service bits.
|
* Service bits.
|
||||||
* @enum {Number}
|
* @enum {Number}
|
||||||
|
|||||||
@ -59,18 +59,17 @@ exports.types = {
|
|||||||
MERKLEBLOCK: 21,
|
MERKLEBLOCK: 21,
|
||||||
GETUTXOS: 22,
|
GETUTXOS: 22,
|
||||||
UTXOS: 23,
|
UTXOS: 23,
|
||||||
HAVEWITNESS: 24,
|
FEEFILTER: 24,
|
||||||
FEEFILTER: 25,
|
SENDCMPCT: 25,
|
||||||
SENDCMPCT: 26,
|
CMPCTBLOCK: 26,
|
||||||
CMPCTBLOCK: 27,
|
GETBLOCKTXN: 27,
|
||||||
GETBLOCKTXN: 28,
|
BLOCKTXN: 28,
|
||||||
BLOCKTXN: 29,
|
ENCINIT: 29,
|
||||||
ENCINIT: 30,
|
ENCACK: 30,
|
||||||
ENCACK: 31,
|
AUTHCHALLENGE: 31,
|
||||||
AUTHCHALLENGE: 32,
|
AUTHREPLY: 32,
|
||||||
AUTHREPLY: 33,
|
AUTHPROPOSE: 33,
|
||||||
AUTHPROPOSE: 34,
|
UNKNOWN: 34,
|
||||||
UNKNOWN: 35,
|
|
||||||
// Internal
|
// Internal
|
||||||
INTERNAL: 100,
|
INTERNAL: 100,
|
||||||
DATA: 101
|
DATA: 101
|
||||||
@ -283,71 +282,6 @@ VersionPacket.prototype.toRaw = function toRaw() {
|
|||||||
return this.toWriter(new StaticWriter(size)).render();
|
return this.toWriter(new StaticWriter(size)).render();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the NETWORK service bit is set.
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
VersionPacket.prototype.hasNetwork = function hasNetwork() {
|
|
||||||
return (this.services & common.services.NETWORK) !== 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the BLOOM service bit is set.
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
VersionPacket.prototype.hasBloom = function hasBloom() {
|
|
||||||
return this.version >= 70011
|
|
||||||
&& (this.services & common.services.BLOOM) !== 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the GETUTXO service bit is set.
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
VersionPacket.prototype.hasUTXO = function hasUTXO() {
|
|
||||||
return (this.services & common.services.GETUTXO) !== 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the WITNESS service bit is set.
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
VersionPacket.prototype.hasWitness = function hasWitness() {
|
|
||||||
return (this.services & common.services.WITNESS) !== 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether required services are available.
|
|
||||||
* @param {Number} services
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
VersionPacket.prototype.hasServices = function hasServices(services) {
|
|
||||||
return (this.services & services) === services;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the protocol version supports getheaders.
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
VersionPacket.prototype.hasHeaders = function hasHeaders() {
|
|
||||||
return this.version >= 31800;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the protocol version supports bip152.
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
VersionPacket.prototype.hasCompact = function hasCompact() {
|
|
||||||
return this.version >= 70014;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from buffer reader.
|
* Inject properties from buffer reader.
|
||||||
* @private
|
* @private
|
||||||
@ -2821,47 +2755,6 @@ UTXOsPacket.fromRaw = function fromRaw(data, enc) {
|
|||||||
return new UTXOsPacket().fromRaw(data);
|
return new UTXOsPacket().fromRaw(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a `havewitness` packet.
|
|
||||||
* @exports HaveWitnessPacket
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
|
|
||||||
function HaveWitnessPacket() {
|
|
||||||
if (!(this instanceof HaveWitnessPacket))
|
|
||||||
return new HaveWitnessPacket();
|
|
||||||
|
|
||||||
Packet.call(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
util.inherits(HaveWitnessPacket, Packet);
|
|
||||||
|
|
||||||
HaveWitnessPacket.prototype.cmd = 'havewitness';
|
|
||||||
HaveWitnessPacket.prototype.type = exports.types.HAVEWITNESS;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate havewitness packet from buffer reader.
|
|
||||||
* @param {BufferReader} br
|
|
||||||
* @returns {HaveWitnessPacket}
|
|
||||||
*/
|
|
||||||
|
|
||||||
HaveWitnessPacket.fromReader = function fromReader(br) {
|
|
||||||
return new HaveWitnessPacket().fromReader(br);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate havewitness packet from serialized data.
|
|
||||||
* @param {Buffer} data
|
|
||||||
* @param {String?} enc
|
|
||||||
* @returns {HaveWitnessPacket}
|
|
||||||
*/
|
|
||||||
|
|
||||||
HaveWitnessPacket.fromRaw = function fromRaw(data, enc) {
|
|
||||||
if (typeof data === 'string')
|
|
||||||
data = new Buffer(data, enc);
|
|
||||||
return new HaveWitnessPacket().fromRaw(data);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a `feefilter` packet.
|
* Represents a `feefilter` packet.
|
||||||
* @exports FeeFilterPacket
|
* @exports FeeFilterPacket
|
||||||
@ -3973,8 +3866,6 @@ exports.fromRaw = function fromRaw(cmd, data) {
|
|||||||
return GetUTXOsPacket.fromRaw(data);
|
return GetUTXOsPacket.fromRaw(data);
|
||||||
case 'utxos':
|
case 'utxos':
|
||||||
return UTXOsPacket.fromRaw(data);
|
return UTXOsPacket.fromRaw(data);
|
||||||
case 'havewitness':
|
|
||||||
return HaveWitnessPacket.fromRaw(data);
|
|
||||||
case 'feefilter':
|
case 'feefilter':
|
||||||
return FeeFilterPacket.fromRaw(data);
|
return FeeFilterPacket.fromRaw(data);
|
||||||
case 'sendcmpct':
|
case 'sendcmpct':
|
||||||
@ -4029,7 +3920,6 @@ exports.FilterClearPacket = FilterClearPacket;
|
|||||||
exports.MerkleBlockPacket = MerkleBlockPacket;
|
exports.MerkleBlockPacket = MerkleBlockPacket;
|
||||||
exports.GetUTXOsPacket = GetUTXOsPacket;
|
exports.GetUTXOsPacket = GetUTXOsPacket;
|
||||||
exports.UTXOsPacket = UTXOsPacket;
|
exports.UTXOsPacket = UTXOsPacket;
|
||||||
exports.HaveWitnessPacket = HaveWitnessPacket;
|
|
||||||
exports.FeeFilterPacket = FeeFilterPacket;
|
exports.FeeFilterPacket = FeeFilterPacket;
|
||||||
exports.SendCmpctPacket = SendCmpctPacket;
|
exports.SendCmpctPacket = SendCmpctPacket;
|
||||||
exports.CmpctBlockPacket = CmpctBlockPacket;
|
exports.CmpctBlockPacket = CmpctBlockPacket;
|
||||||
|
|||||||
147
lib/net/peer.js
147
lib/net/peer.js
@ -28,6 +28,7 @@ var TX = require('../primitives/tx');
|
|||||||
var encoding = require('../utils/encoding');
|
var encoding = require('../utils/encoding');
|
||||||
var errors = require('../protocol/errors');
|
var errors = require('../protocol/errors');
|
||||||
var NetAddress = require('../primitives/netaddress');
|
var NetAddress = require('../primitives/netaddress');
|
||||||
|
var services = common.services;
|
||||||
var invTypes = InvItem.types;
|
var invTypes = InvItem.types;
|
||||||
var packetTypes = packets.types;
|
var packetTypes = packets.types;
|
||||||
var VerifyResult = errors.VerifyResult;
|
var VerifyResult = errors.VerifyResult;
|
||||||
@ -48,15 +49,13 @@ var VerifyResult = errors.VerifyResult;
|
|||||||
* @property {Framer} framer
|
* @property {Framer} framer
|
||||||
* @property {Chain} chain
|
* @property {Chain} chain
|
||||||
* @property {Mempool} mempool
|
* @property {Mempool} mempool
|
||||||
* @property {Object?} version - Version packet payload.
|
* @property {Number} version
|
||||||
* @property {Boolean} destroyed
|
* @property {Boolean} destroyed
|
||||||
* @property {Boolean} ack - Whether verack has been received.
|
* @property {Boolean} ack - Whether verack has been received.
|
||||||
* @property {Boolean} connected
|
* @property {Boolean} connected
|
||||||
* @property {Number} ts
|
* @property {Number} ts
|
||||||
* @property {Boolean} preferHeaders - Whether the peer has
|
* @property {Boolean} preferHeaders - Whether the peer has
|
||||||
* requested getheaders.
|
* requested getheaders.
|
||||||
* @property {Boolean} haveWitness - Whether the peer supports segwit,
|
|
||||||
* either notified via service bits or deprecated `havewitness` packet.
|
|
||||||
* @property {Hash?} hashContinue - The block hash at which to continue
|
* @property {Hash?} hashContinue - The block hash at which to continue
|
||||||
* the sync for the peer.
|
* the sync for the peer.
|
||||||
* @property {Bloom?} spvFilter - The _peer's_ bloom spvFilter.
|
* @property {Bloom?} spvFilter - The _peer's_ bloom spvFilter.
|
||||||
@ -94,6 +93,7 @@ function Peer(pool) {
|
|||||||
this.connected = false;
|
this.connected = false;
|
||||||
this.destroyed = false;
|
this.destroyed = false;
|
||||||
this.ack = false;
|
this.ack = false;
|
||||||
|
this.handshake = false;
|
||||||
this.ts = 0;
|
this.ts = 0;
|
||||||
this.lastSend = 0;
|
this.lastSend = 0;
|
||||||
this.lastRecv = 0;
|
this.lastRecv = 0;
|
||||||
@ -103,12 +103,14 @@ function Peer(pool) {
|
|||||||
this.banScore = 0;
|
this.banScore = 0;
|
||||||
this.invQueue = [];
|
this.invQueue = [];
|
||||||
|
|
||||||
this.version = null;
|
this.version = -1;
|
||||||
|
this.services = 0;
|
||||||
|
this.height = -1;
|
||||||
|
this.agent = null;
|
||||||
|
this.noRelay = false;
|
||||||
this.preferHeaders = false;
|
this.preferHeaders = false;
|
||||||
this.haveWitness = false;
|
|
||||||
this.hashContinue = null;
|
this.hashContinue = null;
|
||||||
this.spvFilter = null;
|
this.spvFilter = null;
|
||||||
this.noRelay = false;
|
|
||||||
this.feeRate = -1;
|
this.feeRate = -1;
|
||||||
this.bip151 = null;
|
this.bip151 = null;
|
||||||
this.bip150 = null;
|
this.bip150 = null;
|
||||||
@ -490,6 +492,8 @@ Peer.prototype.initStall = function initStall() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.initBIP151 = co(function* initBIP151() {
|
Peer.prototype.initBIP151 = co(function* initBIP151() {
|
||||||
|
assert(!this.destroyed);
|
||||||
|
|
||||||
// Send encinit. Wait for handshake to complete.
|
// Send encinit. Wait for handshake to complete.
|
||||||
if (!this.bip151)
|
if (!this.bip151)
|
||||||
return;
|
return;
|
||||||
@ -523,9 +527,12 @@ Peer.prototype.initBIP151 = co(function* initBIP151() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.initBIP150 = co(function* initBIP150() {
|
Peer.prototype.initBIP150 = co(function* initBIP150() {
|
||||||
if (!this.bip151 || !this.bip150)
|
assert(!this.destroyed);
|
||||||
|
|
||||||
|
if (!this.bip150)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
assert(this.bip151);
|
||||||
assert(!this.bip150.completed);
|
assert(!this.bip150.completed);
|
||||||
|
|
||||||
if (!this.bip151.handshake)
|
if (!this.bip151.handshake)
|
||||||
@ -562,34 +569,29 @@ Peer.prototype.initVersion = co(function* initVersion() {
|
|||||||
// Say hello.
|
// Say hello.
|
||||||
this.sendVersion();
|
this.sendVersion();
|
||||||
|
|
||||||
// Advertise our address.
|
|
||||||
if (!this.pool.address.isNull()
|
|
||||||
&& !this.options.selfish
|
|
||||||
&& this.pool.server) {
|
|
||||||
this.send(new packets.AddrPacket([this.pool.address]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.ack) {
|
if (!this.ack) {
|
||||||
yield this.wait(packetTypes.VERACK, 10000);
|
yield this.wait(packetTypes.VERACK, 10000);
|
||||||
assert(this.ack);
|
assert(this.ack);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for _their_ version.
|
// Wait for _their_ version.
|
||||||
if (!this.version) {
|
if (this.version === -1) {
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
'Peer sent a verack without a version (%s).',
|
'Peer sent a verack without a version (%s).',
|
||||||
this.hostname);
|
this.hostname);
|
||||||
|
|
||||||
yield this.wait(packetTypes.VERSION, 10000);
|
yield this.wait(packetTypes.VERSION, 10000);
|
||||||
|
|
||||||
assert(this.version);
|
assert(this.version !== -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.debug('Received verack (%s).', this.hostname);
|
this.handshake = true;
|
||||||
|
|
||||||
|
this.logger.debug('Version handshake complete (%s).', this.hostname);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle `ack` event (called on verack).
|
* Finalize peer after handshake.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -608,15 +610,22 @@ Peer.prototype.finalize = co(function* finalize() {
|
|||||||
self.flushInv();
|
self.flushInv();
|
||||||
}, Peer.INV_INTERVAL);
|
}, Peer.INV_INTERVAL);
|
||||||
|
|
||||||
|
// Advertise our address.
|
||||||
|
if (!this.pool.address.isNull()
|
||||||
|
&& !this.options.selfish
|
||||||
|
&& this.options.listen) {
|
||||||
|
this.send(new packets.AddrPacket([this.pool.address]));
|
||||||
|
}
|
||||||
|
|
||||||
// Ask for headers-only.
|
// Ask for headers-only.
|
||||||
if (this.options.headers) {
|
if (this.options.headers) {
|
||||||
if (this.version.version >= 70012)
|
if (this.version >= common.SENDHEADERS_VERSION)
|
||||||
this.send(new packets.SendHeadersPacket());
|
this.send(new packets.SendHeadersPacket());
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want compact blocks!
|
// We want compact blocks!
|
||||||
if (this.options.compact) {
|
if (this.options.compact) {
|
||||||
if (this.version.version >= 70014)
|
if (this.version >= common.COMPACT_VERSION)
|
||||||
this.sendCompact();
|
this.sendCompact();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -656,7 +665,7 @@ Peer.prototype.announceBlock = function announceBlock(blocks) {
|
|||||||
var inv = [];
|
var inv = [];
|
||||||
var i, block;
|
var i, block;
|
||||||
|
|
||||||
if (!this.ack)
|
if (!this.handshake)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.destroyed)
|
if (this.destroyed)
|
||||||
@ -709,7 +718,7 @@ Peer.prototype.announceTX = function announceTX(txs) {
|
|||||||
var inv = [];
|
var inv = [];
|
||||||
var i, tx, hash, entry;
|
var i, tx, hash, entry;
|
||||||
|
|
||||||
if (!this.ack)
|
if (!this.handshake)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.destroyed)
|
if (this.destroyed)
|
||||||
@ -796,7 +805,7 @@ Peer.prototype.sendInv = function sendInv(items) {
|
|||||||
var hasBlock = false;
|
var hasBlock = false;
|
||||||
var i, item;
|
var i, item;
|
||||||
|
|
||||||
if (!this.ack)
|
if (!this.handshake)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.destroyed)
|
if (this.destroyed)
|
||||||
@ -857,7 +866,7 @@ Peer.prototype.flushInv = function flushInv() {
|
|||||||
Peer.prototype.sendHeaders = function sendHeaders(items) {
|
Peer.prototype.sendHeaders = function sendHeaders(items) {
|
||||||
var i, item, chunk;
|
var i, item, chunk;
|
||||||
|
|
||||||
if (!this.ack)
|
if (!this.handshake)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.destroyed)
|
if (this.destroyed)
|
||||||
@ -918,10 +927,10 @@ Peer.prototype.sendGetAddr = function sendGetAddr() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.sendPing = function sendPing() {
|
Peer.prototype.sendPing = function sendPing() {
|
||||||
if (!this.version)
|
if (!this.handshake)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.version.version <= 60000) {
|
if (this.version <= 60000) {
|
||||||
this.send(new packets.PingPacket());
|
this.send(new packets.PingPacket());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -942,7 +951,7 @@ Peer.prototype.sendPing = function sendPing() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.updateWatch = function updateWatch() {
|
Peer.prototype.updateWatch = function updateWatch() {
|
||||||
if (!this.ack)
|
if (!this.handshake)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!this.options.spv)
|
if (!this.options.spv)
|
||||||
@ -957,7 +966,7 @@ Peer.prototype.updateWatch = function updateWatch() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.sendFeeRate = function sendFeeRate(rate) {
|
Peer.prototype.sendFeeRate = function sendFeeRate(rate) {
|
||||||
if (!this.ack)
|
if (!this.handshake)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.send(new packets.FeeFilterPacket(rate));
|
this.send(new packets.FeeFilterPacket(rate));
|
||||||
@ -1321,7 +1330,7 @@ Peer.prototype.blockType = function blockType() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.haveWitness)
|
if (this.hasWitness())
|
||||||
return invTypes.WITNESS_BLOCK;
|
return invTypes.WITNESS_BLOCK;
|
||||||
|
|
||||||
return invTypes.BLOCK;
|
return invTypes.BLOCK;
|
||||||
@ -1333,7 +1342,7 @@ Peer.prototype.blockType = function blockType() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.txType = function txType() {
|
Peer.prototype.txType = function txType() {
|
||||||
if (this.haveWitness)
|
if (this.hasWitness())
|
||||||
return invTypes.WITNESS_TX;
|
return invTypes.WITNESS_TX;
|
||||||
|
|
||||||
return invTypes.TX;
|
return invTypes.TX;
|
||||||
@ -1434,7 +1443,7 @@ Peer.prototype.onPacket = co(function* onPacket(packet) {
|
|||||||
&& !this.bip151.completed
|
&& !this.bip151.completed
|
||||||
&& packet.type !== packetTypes.ENCINIT
|
&& packet.type !== packetTypes.ENCINIT
|
||||||
&& packet.type !== packetTypes.ENCACK) {
|
&& packet.type !== packetTypes.ENCACK) {
|
||||||
this.bip151.complete(new Error('Message before handshake.'));
|
this.bip151.reject(new Error('Message before handshake.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.bip150
|
if (this.bip150
|
||||||
@ -1442,7 +1451,7 @@ Peer.prototype.onPacket = co(function* onPacket(packet) {
|
|||||||
&& packet.type !== packetTypes.AUTHCHALLENGE
|
&& packet.type !== packetTypes.AUTHCHALLENGE
|
||||||
&& packet.type !== packetTypes.AUTHREPLY
|
&& packet.type !== packetTypes.AUTHREPLY
|
||||||
&& packet.type !== packetTypes.AUTHPROPOSE) {
|
&& packet.type !== packetTypes.AUTHPROPOSE) {
|
||||||
this.bip150.complete(new Error('Message before auth.'));
|
this.bip150.reject(new Error('Message before auth.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.lastMerkle) {
|
if (this.lastMerkle) {
|
||||||
@ -1525,9 +1534,6 @@ Peer.prototype.onPacket = co(function* onPacket(packet) {
|
|||||||
case packetTypes.UTXOS:
|
case packetTypes.UTXOS:
|
||||||
yield this.handleUTXOs(packet);
|
yield this.handleUTXOs(packet);
|
||||||
break;
|
break;
|
||||||
case packetTypes.HAVEWITNESS:
|
|
||||||
yield this.handleHaveWitness(packet);
|
|
||||||
break;
|
|
||||||
case packetTypes.FEEFILTER:
|
case packetTypes.FEEFILTER:
|
||||||
yield this.handleFeeFilter(packet);
|
yield this.handleFeeFilter(packet);
|
||||||
break;
|
break;
|
||||||
@ -1750,17 +1756,6 @@ Peer.prototype.handleGetUTXOs = co(function* handleGetUTXOs(packet) {
|
|||||||
this.send(utxos);
|
this.send(utxos);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle `havewitness` packet.
|
|
||||||
* @private
|
|
||||||
* @param {HaveWitnessPacket}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Peer.prototype.handleHaveWitness = co(function* handleHaveWitness(packet) {
|
|
||||||
this.haveWitness = true;
|
|
||||||
this.emit('havewitness');
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle `getheaders` packet.
|
* Handle `getheaders` packet.
|
||||||
* @private
|
* @private
|
||||||
@ -1860,39 +1855,42 @@ Peer.prototype.handleGetBlocks = co(function* handleGetBlocks(packet) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.handleVersion = co(function* handleVersion(packet) {
|
Peer.prototype.handleVersion = co(function* handleVersion(packet) {
|
||||||
if (this.version)
|
if (this.version !== -1)
|
||||||
throw new Error('Peer sent a duplicate version.');
|
throw new Error('Peer sent a duplicate version.');
|
||||||
|
|
||||||
this.version = packet;
|
this.version = packet.version;
|
||||||
|
this.services = packet.services;
|
||||||
|
this.height = packet.height;
|
||||||
|
this.agent = packet.agent;
|
||||||
this.noRelay = packet.noRelay;
|
this.noRelay = packet.noRelay;
|
||||||
|
|
||||||
if (this.options.witness)
|
|
||||||
this.haveWitness = packet.hasWitness();
|
|
||||||
|
|
||||||
if (!this.network.selfConnect) {
|
if (!this.network.selfConnect) {
|
||||||
if (util.equal(packet.nonce, this.pool.nonce))
|
if (util.equal(packet.nonce, this.pool.nonce))
|
||||||
throw new Error('We connected to ourself. Oops.');
|
throw new Error('We connected to ourself. Oops.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packet.version < common.MIN_VERSION)
|
if (this.version < common.MIN_VERSION)
|
||||||
throw new Error('Peer does not support required protocol version.');
|
throw new Error('Peer does not support required protocol version.');
|
||||||
|
|
||||||
if (this.outbound) {
|
if (this.outbound) {
|
||||||
if (!packet.hasNetwork())
|
if (!(this.services & services.NETWORK))
|
||||||
throw new Error('Peer does not support network services.');
|
throw new Error('Peer does not support network services.');
|
||||||
|
|
||||||
if (this.options.headers) {
|
if (this.options.headers) {
|
||||||
if (!packet.hasHeaders())
|
if (this.version < common.HEADERS_VERSION)
|
||||||
throw new Error('Peer does not support getheaders.');
|
throw new Error('Peer does not support getheaders.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options.spv) {
|
if (this.options.spv) {
|
||||||
if (!packet.hasBloom())
|
if (!(this.services & services.BLOOM))
|
||||||
|
throw new Error('Peer does not support BIP37.');
|
||||||
|
|
||||||
|
if (this.version < common.BLOOM_VERSION)
|
||||||
throw new Error('Peer does not support BIP37.');
|
throw new Error('Peer does not support BIP37.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options.witness) {
|
if (this.options.witness) {
|
||||||
if (!this.haveWitness)
|
if (!(this.services & services.WITNESS))
|
||||||
throw new Error('Peer does not support segregated witness.');
|
throw new Error('Peer does not support segregated witness.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1911,6 +1909,7 @@ Peer.prototype.handleVersion = co(function* handleVersion(packet) {
|
|||||||
Peer.prototype.handleVerack = co(function* handleVerack(packet) {
|
Peer.prototype.handleVerack = co(function* handleVerack(packet) {
|
||||||
this.ack = true;
|
this.ack = true;
|
||||||
this.emit('verack');
|
this.emit('verack');
|
||||||
|
this.logger.debug('Received verack (%s).', this.hostname);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2797,7 +2796,7 @@ Peer.prototype.handleBlockTxn = co(function* handleBlockTxn(packet) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.sendAlert = function sendAlert(alert) {
|
Peer.prototype.sendAlert = function sendAlert(alert) {
|
||||||
if (!this.ack)
|
if (!this.handshake)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!this.invFilter.added(alert.hash()))
|
if (!this.invFilter.added(alert.hash()))
|
||||||
@ -2872,13 +2871,10 @@ Peer.prototype.sendGetBlocks = function getBlocks(locator, stop) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.sendMempool = function sendMempool() {
|
Peer.prototype.sendMempool = function sendMempool() {
|
||||||
if (!this.ack)
|
if (!this.handshake)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!this.version)
|
if (!(this.services & services.BLOOM)) {
|
||||||
return;
|
|
||||||
|
|
||||||
if (!this.version.hasBloom()) {
|
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
'Cannot request mempool for non-bloom peer (%s).',
|
'Cannot request mempool for non-bloom peer (%s).',
|
||||||
this.hostname);
|
this.hostname);
|
||||||
@ -3026,16 +3022,16 @@ Peer.prototype.sync = co(function* sync() {
|
|||||||
if (!this.pool.syncing)
|
if (!this.pool.syncing)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!this.ack)
|
if (!this.handshake)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.syncSent)
|
if (this.syncSent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!this.version.hasNetwork())
|
if (!(this.services & services.NETWORK))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.options.witness && !this.haveWitness)
|
if (this.options.witness && !this.hasWitness())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!this.isLoader()) {
|
if (!this.isLoader()) {
|
||||||
@ -3063,6 +3059,25 @@ Peer.prototype.sync = co(function* sync() {
|
|||||||
return yield this.getBlocks();
|
return yield this.getBlocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether required services are available.
|
||||||
|
* @param {Number} services
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Peer.prototype.hasServices = function hasServices(services) {
|
||||||
|
return (this.services & services) === services;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the WITNESS service bit is set.
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Peer.prototype.hasWitness = function hasWitness() {
|
||||||
|
return (this.services & services.WITNESS) !== 0;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect the peer.
|
* Inspect the peer.
|
||||||
* @returns {String}
|
* @returns {String}
|
||||||
@ -3070,7 +3085,7 @@ Peer.prototype.sync = co(function* sync() {
|
|||||||
|
|
||||||
Peer.prototype.inspect = function inspect() {
|
Peer.prototype.inspect = function inspect() {
|
||||||
return '<Peer:'
|
return '<Peer:'
|
||||||
+ ' ack=' + this.ack
|
+ ' handshake=' + this.handshake
|
||||||
+ ' host=' + this.hostname
|
+ ' host=' + this.hostname
|
||||||
+ ' outbound=' + this.outbound
|
+ ' outbound=' + this.outbound
|
||||||
+ ' ping=' + this.minPing
|
+ ' ping=' + this.minPing
|
||||||
|
|||||||
@ -747,10 +747,10 @@ Pool.prototype.handleOpen = function handleOpen(peer) {
|
|||||||
if (!peer.outbound)
|
if (!peer.outbound)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.hosts.markAck(peer.hostname, peer.version.services);
|
this.hosts.markAck(peer.hostname, peer.services);
|
||||||
|
|
||||||
// If we don't have an ack'd loader yet, use this peer.
|
// If we don't have an ack'd loader yet, use this peer.
|
||||||
if (!this.peers.load || !this.peers.load.ack)
|
if (!this.peers.load || !this.peers.load.handshake)
|
||||||
this.setLoader(peer);
|
this.setLoader(peer);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1091,7 +1091,7 @@ Pool.prototype._handleBlockInv = co(function* handleBlockInv(peer, hashes) {
|
|||||||
if (!this.chain.synced && !peer.isLoader())
|
if (!this.chain.synced && !peer.isLoader())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.options.witness && !peer.haveWitness)
|
if (this.options.witness && !peer.hasWitness())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Request headers instead.
|
// Request headers instead.
|
||||||
@ -1543,7 +1543,7 @@ Pool.prototype.getBlock = function getBlock(peer, hash) {
|
|||||||
if (!this.loaded)
|
if (!this.loaded)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!peer.ack)
|
if (!peer.handshake)
|
||||||
throw new Error('Peer handshake not complete (getdata).');
|
throw new Error('Peer handshake not complete (getdata).');
|
||||||
|
|
||||||
if (peer.destroyed)
|
if (peer.destroyed)
|
||||||
@ -1596,7 +1596,7 @@ Pool.prototype.getTX = function getTX(peer, hashes) {
|
|||||||
if (!this.loaded)
|
if (!this.loaded)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!peer.ack)
|
if (!peer.handshake)
|
||||||
throw new Error('Peer handshake not complete (getdata).');
|
throw new Error('Peer handshake not complete (getdata).');
|
||||||
|
|
||||||
if (peer.destroyed)
|
if (peer.destroyed)
|
||||||
|
|||||||
@ -95,42 +95,6 @@ NetAddress.fromOptions = function fromOptions(options) {
|
|||||||
return new NetAddress().fromOptions(options);
|
return new NetAddress().fromOptions(options);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the NETWORK service bit is set.
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
NetAddress.prototype.hasNetwork = function hasNetwork() {
|
|
||||||
return (this.services & common.services.NETWORK) !== 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the BLOOM service bit is set.
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
NetAddress.prototype.hasBloom = function hasBloom() {
|
|
||||||
return (this.services & common.services.BLOOM) !== 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the GETUTXO service bit is set.
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
NetAddress.prototype.hasUTXO = function hasUTXO() {
|
|
||||||
return (this.services & common.services.GETUTXO) !== 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the WITNESS service bit is set.
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
NetAddress.prototype.hasWitness = function hasWitness() {
|
|
||||||
return (this.services & common.services.WITNESS) !== 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether required services are available.
|
* Test whether required services are available.
|
||||||
* @param {Number} services
|
* @param {Number} services
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user