packets
This commit is contained in:
parent
9b097f97b9
commit
5da0aceb38
@ -13,7 +13,7 @@ var scrypt = require('./scrypt');
|
|||||||
var scryptAsync = require('./scrypt-async');
|
var scryptAsync = require('./scrypt-async');
|
||||||
var utils = require('../utils/utils');
|
var utils = require('../utils/utils');
|
||||||
var native = require('../utils/native');
|
var native = require('../utils/native');
|
||||||
var nativeCrypto, supersha, hash, aes;
|
var nativeCrypto, hash, aes;
|
||||||
|
|
||||||
var isBrowser =
|
var isBrowser =
|
||||||
(typeof process !== 'undefined' && process.browser)
|
(typeof process !== 'undefined' && process.browser)
|
||||||
|
|||||||
@ -123,6 +123,7 @@ function Environment() {
|
|||||||
this.require('reader', './utils/reader');
|
this.require('reader', './utils/reader');
|
||||||
this.require('writer', './utils/writer');
|
this.require('writer', './utils/writer');
|
||||||
this.require('lru', './utils/lru');
|
this.require('lru', './utils/lru');
|
||||||
|
this.require('bloom', './utils/bloom');
|
||||||
this.require('uri', './utils/uri');
|
this.require('uri', './utils/uri');
|
||||||
this.require('errors', './utils/errors');
|
this.require('errors', './utils/errors');
|
||||||
|
|
||||||
@ -147,7 +148,6 @@ function Environment() {
|
|||||||
this.require('sc', './script/sigcache');
|
this.require('sc', './script/sigcache');
|
||||||
|
|
||||||
// Primitives
|
// Primitives
|
||||||
this.require('bloom', './primitives/bloom');
|
|
||||||
this.require('address', './primitives/address');
|
this.require('address', './primitives/address');
|
||||||
this.require('outpoint', './primitives/outpoint');
|
this.require('outpoint', './primitives/outpoint');
|
||||||
this.require('input', './primitives/input');
|
this.require('input', './primitives/input');
|
||||||
@ -162,6 +162,7 @@ function Environment() {
|
|||||||
this.require('merkleblock', './primitives/merkleblock');
|
this.require('merkleblock', './primitives/merkleblock');
|
||||||
this.require('headers', './primitives/headers');
|
this.require('headers', './primitives/headers');
|
||||||
this.require('keyring', './primitives/keyring');
|
this.require('keyring', './primitives/keyring');
|
||||||
|
this.require('netaddress', './primitives/netaddress');
|
||||||
|
|
||||||
// HD
|
// HD
|
||||||
this.require('hd', './hd/hd');
|
this.require('hd', './hd/hd');
|
||||||
|
|||||||
@ -11,7 +11,7 @@ var utils = require('../utils/utils');
|
|||||||
var crypto = require('../crypto/crypto');
|
var crypto = require('../crypto/crypto');
|
||||||
var assert = utils.assert;
|
var assert = utils.assert;
|
||||||
var constants = bcoin.constants;
|
var constants = bcoin.constants;
|
||||||
var NetworkAddress = bcoin.packets.NetworkAddress;
|
var NetworkAddress = require('../primitives/netaddress');
|
||||||
var fs;
|
var fs;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -12,12 +12,10 @@ var EventEmitter = require('events').EventEmitter;
|
|||||||
var bcoin = require('../env');
|
var bcoin = require('../env');
|
||||||
var utils = require('../utils/utils');
|
var utils = require('../utils/utils');
|
||||||
var crypto = require('../crypto/crypto');
|
var crypto = require('../crypto/crypto');
|
||||||
|
var packets = require('./packets');
|
||||||
var assert = utils.assert;
|
var assert = utils.assert;
|
||||||
var constants = bcoin.constants;
|
var constants = bcoin.constants;
|
||||||
|
|
||||||
var ZERO_SIG = new Buffer(64);
|
|
||||||
ZERO_SIG.fill(0);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a BIP150 input and output stream.
|
* Represents a BIP150 input and output stream.
|
||||||
* @exports BIP150
|
* @exports BIP150
|
||||||
@ -76,9 +74,7 @@ BIP150.prototype.isAuthed = function isAuthed() {
|
|||||||
return this.challengeReceived && this.replyReceived;
|
return this.challengeReceived && this.replyReceived;
|
||||||
};
|
};
|
||||||
|
|
||||||
BIP150.prototype.challenge = function challenge(payload) {
|
BIP150.prototype.challenge = function challenge(hash) {
|
||||||
var p = bcoin.reader(payload);
|
|
||||||
var hash = p.readHash();
|
|
||||||
var type = this.outbound ? 'r' : 'i';
|
var type = this.outbound ? 'r' : 'i';
|
||||||
var msg, sig;
|
var msg, sig;
|
||||||
|
|
||||||
@ -92,7 +88,7 @@ BIP150.prototype.challenge = function challenge(payload) {
|
|||||||
msg = this.hash(this.input.sid, type, this.publicKey);
|
msg = this.hash(this.input.sid, type, this.publicKey);
|
||||||
|
|
||||||
if (!crypto.ccmp(hash, msg))
|
if (!crypto.ccmp(hash, msg))
|
||||||
return ZERO_SIG;
|
return constants.ZERO_SIG64;
|
||||||
|
|
||||||
if (this.isAuthed()) {
|
if (this.isAuthed()) {
|
||||||
this.auth = true;
|
this.auth = true;
|
||||||
@ -105,9 +101,7 @@ BIP150.prototype.challenge = function challenge(payload) {
|
|||||||
return bcoin.ec.fromDER(sig);
|
return bcoin.ec.fromDER(sig);
|
||||||
};
|
};
|
||||||
|
|
||||||
BIP150.prototype.reply = function reply(payload) {
|
BIP150.prototype.reply = function reply(data) {
|
||||||
var p = bcoin.reader(payload);
|
|
||||||
var data = p.readBytes(64);
|
|
||||||
var type = this.outbound ? 'i' : 'r';
|
var type = this.outbound ? 'i' : 'r';
|
||||||
var sig, msg, result;
|
var sig, msg, result;
|
||||||
|
|
||||||
@ -115,7 +109,7 @@ BIP150.prototype.reply = function reply(payload) {
|
|||||||
assert(!this.replyReceived, 'Peer replied twice.');
|
assert(!this.replyReceived, 'Peer replied twice.');
|
||||||
this.replyReceived = true;
|
this.replyReceived = true;
|
||||||
|
|
||||||
if (utils.equal(data, ZERO_SIG))
|
if (utils.equal(data, constants.ZERO_SIG64))
|
||||||
throw new Error('Auth failure.');
|
throw new Error('Auth failure.');
|
||||||
|
|
||||||
if (!this.peerIdentity)
|
if (!this.peerIdentity)
|
||||||
@ -141,9 +135,7 @@ BIP150.prototype.reply = function reply(payload) {
|
|||||||
return this.hash(this.input.sid, 'p', this.publicKey);
|
return this.hash(this.input.sid, 'p', this.publicKey);
|
||||||
};
|
};
|
||||||
|
|
||||||
BIP150.prototype.propose = function propose(payload) {
|
BIP150.prototype.propose = function propose(hash) {
|
||||||
var p = bcoin.reader(payload);
|
|
||||||
var hash = p.readHash();
|
|
||||||
var match;
|
var match;
|
||||||
|
|
||||||
assert(!this.outbound, 'Outbound peer tried to propose.');
|
assert(!this.outbound, 'Outbound peer tried to propose.');
|
||||||
@ -167,8 +159,7 @@ BIP150.prototype.propose = function propose(payload) {
|
|||||||
return this.hash(this.output.sid, 'r', this.peerIdentity);
|
return this.hash(this.output.sid, 'r', this.peerIdentity);
|
||||||
};
|
};
|
||||||
|
|
||||||
BIP150.prototype.toChallenge = function toChallenge(writer) {
|
BIP150.prototype.toChallenge = function toChallenge() {
|
||||||
var p = new bcoin.writer(writer);
|
|
||||||
var msg;
|
var msg;
|
||||||
|
|
||||||
assert(this.bip151.handshake, 'No BIP151 handshake before challenge.');
|
assert(this.bip151.handshake, 'No BIP151 handshake before challenge.');
|
||||||
@ -180,12 +171,7 @@ BIP150.prototype.toChallenge = function toChallenge(writer) {
|
|||||||
assert(!this.challengeSent, 'Cannot initiate challenge twice.');
|
assert(!this.challengeSent, 'Cannot initiate challenge twice.');
|
||||||
this.challengeSent = true;
|
this.challengeSent = true;
|
||||||
|
|
||||||
p.writeBytes(msg);
|
return new packets.AuthChallengePacket(msg);
|
||||||
|
|
||||||
if (!writer)
|
|
||||||
p = p.render();
|
|
||||||
|
|
||||||
return p;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
BIP150.prototype.rekey = function rekey(sid, key, req, res) {
|
BIP150.prototype.rekey = function rekey(sid, key, req, res) {
|
||||||
|
|||||||
@ -19,6 +19,7 @@ var crypto = require('../crypto/crypto');
|
|||||||
var assert = utils.assert;
|
var assert = utils.assert;
|
||||||
var constants = bcoin.constants;
|
var constants = bcoin.constants;
|
||||||
var chachapoly = require('../crypto/chachapoly');
|
var chachapoly = require('../crypto/chachapoly');
|
||||||
|
var packets = require('./packets');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
@ -526,19 +527,10 @@ BIP151.prototype.isReady = function isReady() {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BIP151.prototype.toEncinit = function toEncinit(writer) {
|
BIP151.prototype.toEncinit = function toEncinit() {
|
||||||
var p = bcoin.writer(writer);
|
|
||||||
|
|
||||||
p.writeBytes(this.input.getPublicKey());
|
|
||||||
p.writeU8(this.input.cipher);
|
|
||||||
|
|
||||||
if (!writer)
|
|
||||||
p = p.render();
|
|
||||||
|
|
||||||
assert(!this.initSent, 'Cannot init twice.');
|
assert(!this.initSent, 'Cannot init twice.');
|
||||||
this.initSent = true;
|
this.initSent = true;
|
||||||
|
return new packets.EncinitPacket(this.input.getPublicKey(), this.input.cipher);
|
||||||
return p;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -547,16 +539,8 @@ BIP151.prototype.toEncinit = function toEncinit(writer) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BIP151.prototype.toEncack = function toEncack(writer) {
|
BIP151.prototype.toEncack = function toEncack() {
|
||||||
var p = bcoin.writer(writer);
|
|
||||||
|
|
||||||
assert(this.output.prk, 'Cannot ack before init.');
|
assert(this.output.prk, 'Cannot ack before init.');
|
||||||
|
|
||||||
p.writeBytes(this.output.getPublicKey());
|
|
||||||
|
|
||||||
if (!writer)
|
|
||||||
p = p.render();
|
|
||||||
|
|
||||||
assert(!this.ackSent, 'Cannot ack twice.');
|
assert(!this.ackSent, 'Cannot ack twice.');
|
||||||
this.ackSent = true;
|
this.ackSent = true;
|
||||||
|
|
||||||
@ -565,7 +549,7 @@ BIP151.prototype.toEncack = function toEncack(writer) {
|
|||||||
this.emit('handshake');
|
this.emit('handshake');
|
||||||
}
|
}
|
||||||
|
|
||||||
return p;
|
return new packets.EncackPacket(this.output.getPublicKey());
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -575,17 +559,9 @@ BIP151.prototype.toEncack = function toEncack(writer) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BIP151.prototype.toRekey = function toRekey(writer) {
|
BIP151.prototype.toRekey = function toRekey() {
|
||||||
var p = bcoin.writer(writer);
|
|
||||||
|
|
||||||
assert(this.handshake, 'Cannot rekey before handshake.');
|
assert(this.handshake, 'Cannot rekey before handshake.');
|
||||||
|
return new packets.EncackPacket(constants.ZERO_KEY);
|
||||||
p.writeBytes(constants.ZERO_KEY);
|
|
||||||
|
|
||||||
if (!writer)
|
|
||||||
p = p.render();
|
|
||||||
|
|
||||||
return p;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -593,16 +569,10 @@ BIP151.prototype.toRekey = function toRekey(writer) {
|
|||||||
* @param {Buffer}
|
* @param {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BIP151.prototype.encinit = function encinit(data) {
|
BIP151.prototype.encinit = function encinit(publicKey, cipher) {
|
||||||
var p = bcoin.reader(data);
|
assert(cipher === this.output.cipher, 'Cipher mismatch.');
|
||||||
var publicKey = p.readBytes(33);
|
|
||||||
var cipher = p.readU8();
|
|
||||||
|
|
||||||
assert(!this.initReceived, 'Already initialized.');
|
assert(!this.initReceived, 'Already initialized.');
|
||||||
this.initReceived = true;
|
this.initReceived = true;
|
||||||
|
|
||||||
assert(cipher === this.output.cipher, 'Cipher mismatch.');
|
|
||||||
|
|
||||||
this.output.init(publicKey);
|
this.output.init(publicKey);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -611,10 +581,7 @@ BIP151.prototype.encinit = function encinit(data) {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BIP151.prototype.encack = function encack(data) {
|
BIP151.prototype.encack = function encack(publicKey) {
|
||||||
var p = bcoin.reader(data);
|
|
||||||
var publicKey = p.readBytes(33);
|
|
||||||
|
|
||||||
assert(this.initSent, 'Unsolicited ACK.');
|
assert(this.initSent, 'Unsolicited ACK.');
|
||||||
|
|
||||||
if (utils.equal(publicKey, constants.ZERO_KEY)) {
|
if (utils.equal(publicKey, constants.ZERO_KEY)) {
|
||||||
|
|||||||
@ -552,43 +552,6 @@ TXResponse.prototype.toRaw = function toRaw(witness, writer) {
|
|||||||
return p;
|
return p;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a SendCompact message (bip152): `sendcmpct` packet.
|
|
||||||
* @see https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
|
|
||||||
function SendCompact(mode, version) {
|
|
||||||
if (!(this instanceof SendCompact))
|
|
||||||
return new SendCompact(mode, version);
|
|
||||||
|
|
||||||
this.mode = mode || 0;
|
|
||||||
this.version = version || 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendCompact.prototype.fromRaw = function fromRaw(data) {
|
|
||||||
var p = bcoin.reader(data);
|
|
||||||
this.mode = p.readU8();
|
|
||||||
this.version = p.readU53();
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
SendCompact.fromRaw = function fromRaw(data) {
|
|
||||||
return new SendCompact().fromRaw(data);
|
|
||||||
};
|
|
||||||
|
|
||||||
SendCompact.prototype.toRaw = function toRaw(writer) {
|
|
||||||
var p = bcoin.writer(writer);
|
|
||||||
|
|
||||||
p.writeU8(this.mode);
|
|
||||||
p.writeU64(this.version);
|
|
||||||
|
|
||||||
if (!writer)
|
|
||||||
p = p.render();
|
|
||||||
|
|
||||||
return p;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
@ -596,4 +559,3 @@ SendCompact.prototype.toRaw = function toRaw(writer) {
|
|||||||
exports.CompactBlock = CompactBlock;
|
exports.CompactBlock = CompactBlock;
|
||||||
exports.TXRequest = TXRequest;
|
exports.TXRequest = TXRequest;
|
||||||
exports.TXResponse = TXResponse;
|
exports.TXResponse = TXResponse;
|
||||||
exports.SendCompact = SendCompact;
|
|
||||||
|
|||||||
@ -11,8 +11,6 @@ var bcoin = require('../env');
|
|||||||
var utils = require('../utils/utils');
|
var utils = require('../utils/utils');
|
||||||
var crypto = require('../crypto/crypto');
|
var crypto = require('../crypto/crypto');
|
||||||
var assert = utils.assert;
|
var assert = utils.assert;
|
||||||
var BufferWriter = require('../utils/writer');
|
|
||||||
var DUMMY = new Buffer(0);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protocol packet framer
|
* Protocol packet framer
|
||||||
@ -77,436 +75,6 @@ Framer.prototype.packet = function packet(cmd, payload, checksum) {
|
|||||||
return packet;
|
return packet;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a version packet with a header.
|
|
||||||
* @param {VersionPacket} payload
|
|
||||||
* @returns {Buffer} version packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.version = function version(payload) {
|
|
||||||
return this.packet('version', payload.toRaw());
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a verack packet with a header.
|
|
||||||
* @returns {Buffer} verack packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.verack = function verack() {
|
|
||||||
return this.packet('verack', DUMMY);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a ping packet with a header.
|
|
||||||
* @param {BN} nonce
|
|
||||||
* @returns {Buffer} ping packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.ping = function ping(nonce) {
|
|
||||||
if (!nonce)
|
|
||||||
return this.packet('ping', DUMMY);
|
|
||||||
return this.packet('ping', framePing(nonce));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a pong packet with a header.
|
|
||||||
* @param {BN} nonce
|
|
||||||
* @returns {Buffer} pong packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.pong = function pong(nonce) {
|
|
||||||
return this.packet('pong', framePing(nonce));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an alert packet with a header.
|
|
||||||
* @param {AlertPacket} alert
|
|
||||||
* @returns {Buffer} alert packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.alert = function _alert(alert) {
|
|
||||||
return this.packet('alert', alert.toRaw());
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a getaddr packet with a header.
|
|
||||||
* @returns {Buffer} getaddr packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.getAddr = function getAddr() {
|
|
||||||
return this.packet('getaddr', DUMMY);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an addr packet with a header.
|
|
||||||
* @param {NetworkAddress[]} hosts
|
|
||||||
* @returns {Buffer} addr packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.addr = function addr(hosts) {
|
|
||||||
return this.packet('addr', frameAddr(hosts));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an inv packet with a header.
|
|
||||||
* @param {InvItem[]} items
|
|
||||||
* @returns {Buffer} inv packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.inv = function inv(items) {
|
|
||||||
return this.packet('inv', frameItems(items));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a getdata packet with a header.
|
|
||||||
* @param {InvItem[]} items
|
|
||||||
* @returns {Buffer} getdata packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.getData = function getData(items) {
|
|
||||||
return this.packet('getdata', frameItems(items));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a notfound packet with a header.
|
|
||||||
* @param {InvItem[]} items
|
|
||||||
* @returns {Buffer} notfound packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.notFound = function notFound(items) {
|
|
||||||
return this.packet('notfound', frameItems(items));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a getblocks packet with a header.
|
|
||||||
* @param {GetBlocksPacket} data
|
|
||||||
* @returns {Buffer} getblocks packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.getBlocks = function getBlocks(data) {
|
|
||||||
return this.packet('getblocks', data.toRaw());
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a getheaders packet with a header.
|
|
||||||
* @param {GetBlocksPacket} data
|
|
||||||
* @returns {Buffer} getheaders packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.getHeaders = function getHeaders(data) {
|
|
||||||
return this.packet('getheaders', data.toRaw());
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a headers packet with a header.
|
|
||||||
* @param {Headers[]} headers
|
|
||||||
* @returns {Buffer} headers packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.headers = function _headers(headers) {
|
|
||||||
return this.packet('headers', frameItems(headers));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a sendheaders packet with a header.
|
|
||||||
* @returns {Buffer} sendheaders packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.sendHeaders = function sendHeaders() {
|
|
||||||
return this.packet('sendheaders', DUMMY);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a block packet with a header.
|
|
||||||
* @param {Block} block
|
|
||||||
* @returns {Buffer} block packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.block = function _block(block) {
|
|
||||||
return this.packet('block', block.toNormal());
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a block packet with a header,
|
|
||||||
* using witness serialization.
|
|
||||||
* @param {Block} block
|
|
||||||
* @returns {Buffer} block packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.witnessBlock = function witnessBlock(block) {
|
|
||||||
return this.packet('block', block.toRaw());
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a tx packet with a header.
|
|
||||||
* @param {TX} tx
|
|
||||||
* @returns {Buffer} tx packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.tx = function _tx(tx) {
|
|
||||||
return this.packet('tx', tx.toNormal(), tx.hash());
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a tx packet with a header,
|
|
||||||
* using witness serialization.
|
|
||||||
* @param {TX} tx
|
|
||||||
* @returns {Buffer} tx packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.witnessTX = function witnessTX(tx) {
|
|
||||||
var checksum;
|
|
||||||
|
|
||||||
// Save some time by using the
|
|
||||||
// cached hash as our checksum.
|
|
||||||
if (tx.hasWitness()) {
|
|
||||||
// We can't use the coinbase
|
|
||||||
// hash since it is all zeroes.
|
|
||||||
// We really shouldn't be
|
|
||||||
// relaying coinbases in the
|
|
||||||
// first place, but oh well.
|
|
||||||
if (!tx.isCoinbase())
|
|
||||||
checksum = tx.witnessHash();
|
|
||||||
} else {
|
|
||||||
checksum = tx.hash();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.packet('tx', tx.toRaw(), checksum);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a reject packet with a header.
|
|
||||||
* @param {RejectPacket} details
|
|
||||||
* @returns {Buffer} reject packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.reject = function reject(details) {
|
|
||||||
return this.packet('reject', details.toRaw());
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a mempool packet with a header.
|
|
||||||
* @returns {Buffer} mempool packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.mempool = function mempool() {
|
|
||||||
return this.packet('mempool', DUMMY);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a filterload packet with a header.
|
|
||||||
* @param {Bloom} filter
|
|
||||||
* @returns {Buffer} filterload packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.filterLoad = function filterLoad(filter) {
|
|
||||||
return this.packet('filterload', filter.toRaw());
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a filteradd packet with a header.
|
|
||||||
* @param {Buffer} data
|
|
||||||
* @returns {Buffer} filteradd packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.filterAdd = function filterAdd(data) {
|
|
||||||
return this.packet('filteradd', frameFilterAdd(data));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a filterclear packet with a header.
|
|
||||||
* @returns {Buffer} filterclear packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.filterClear = function filterClear() {
|
|
||||||
return this.packet('filterclear', DUMMY);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a merkleblock packet with a header.
|
|
||||||
* @param {MerkleBlock} block
|
|
||||||
* @returns {Buffer} merkleblock packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.merkleBlock = function merkleBlock(block) {
|
|
||||||
return this.packet('merkleblock', block.toRaw());
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a getutxos packet with a header.
|
|
||||||
* @param {GetUTXOsPacket} data
|
|
||||||
* @returns {Buffer} getutxos packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.getUTXOs = function getUTXOs(data) {
|
|
||||||
return this.packet('getutxos', data.toRaw());
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a utxos packet with a header.
|
|
||||||
* @param {UTXOsPacket} utxos
|
|
||||||
* @returns {Buffer} utxos packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.UTXOs = function UTXOs(utxos) {
|
|
||||||
return this.packet('utxos', utxos.toRaw());
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a havewitness packet with a header.
|
|
||||||
* @returns {Buffer} havewitness packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.haveWitness = function haveWitness() {
|
|
||||||
return this.packet('havewitness', DUMMY);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a feefilter packet with a header.
|
|
||||||
* @param {Rate} rate
|
|
||||||
* @returns {Buffer} feefilter packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.feeFilter = function feeFilter(rate) {
|
|
||||||
return this.packet('feefilter', frameFeeFilter(rate));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a sendcmpct packet with a header.
|
|
||||||
* @param {SendCompact} data
|
|
||||||
* @returns {Buffer} sendcmpct packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.sendCmpct = function sendCmpct(data) {
|
|
||||||
return this.packet('sendcmpct', data.toRaw());
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a cmpctblock packet with a header.
|
|
||||||
* @param {CompactBlock} block
|
|
||||||
* @returns {Buffer} cmpctblock packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.cmpctBlock = function cmpctBlock(block) {
|
|
||||||
return this.packet('cmpctblock', block.toRaw(false));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a getblocktxn packet with a header.
|
|
||||||
* @param {TXRequest} req
|
|
||||||
* @returns {Buffer} getblocktxn packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.getBlockTxn = function getBlockTxn(req) {
|
|
||||||
return this.packet('getblocktxn', req.toRaw());
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a blocktxn packet with a header.
|
|
||||||
* @param {TXResponse} res
|
|
||||||
* @returns {Buffer} blocktxn packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.blockTxn = function blockTxn(res) {
|
|
||||||
return this.packet('blocktxn', res.toRaw(false));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an encinit packet with a header.
|
|
||||||
* @param {Buffer} data
|
|
||||||
* @returns {Buffer} encinit packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.encinit = function encinit(data) {
|
|
||||||
return this.packet('encinit', data);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an encack packet with a header.
|
|
||||||
* @param {Buffer} data
|
|
||||||
* @returns {Buffer} encack packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.encack = function encack(data) {
|
|
||||||
return this.packet('encack', data);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a authchallenge packet with a header.
|
|
||||||
* @param {Buffer} data
|
|
||||||
* @returns {Buffer} authchallenge packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.authChallenge = function authChallenge(data) {
|
|
||||||
return this.packet('authchallenge', data);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a authreply packet with a header.
|
|
||||||
* @param {Buffer} data
|
|
||||||
* @returns {Buffer} authreply packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.authReply = function authReply(data) {
|
|
||||||
return this.packet('authreply', data);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a authpropose packet with a header.
|
|
||||||
* @param {Buffer} data
|
|
||||||
* @returns {Buffer} authpropose packet.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Framer.prototype.authPropose = function authPropose(data) {
|
|
||||||
return this.packet('authpropose', data);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Helpers
|
|
||||||
*/
|
|
||||||
|
|
||||||
function frameItems(items) {
|
|
||||||
var p = new BufferWriter();
|
|
||||||
var i;
|
|
||||||
|
|
||||||
p.writeVarint(items.length);
|
|
||||||
|
|
||||||
for (i = 0; i < items.length; i++)
|
|
||||||
items[i].toRaw(p);
|
|
||||||
|
|
||||||
return p.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
function framePing(nonce) {
|
|
||||||
var p = new BufferWriter();
|
|
||||||
p.writeU64(nonce);
|
|
||||||
return p.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
function frameAddr(hosts) {
|
|
||||||
var p = new BufferWriter();
|
|
||||||
var i;
|
|
||||||
|
|
||||||
p.writeVarint(hosts.length);
|
|
||||||
|
|
||||||
for (i = 0; i < hosts.length; i++)
|
|
||||||
hosts[i].toRaw(true, p);
|
|
||||||
|
|
||||||
return p.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
function frameFilterAdd(data) {
|
|
||||||
var p = new BufferWriter();
|
|
||||||
p.writeVarBytes(data);
|
|
||||||
return p.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
function frameFeeFilter(rate) {
|
|
||||||
var p = new BufferWriter();
|
|
||||||
p.write64(rate);
|
|
||||||
return p.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
2306
lib/net/packets.js
2306
lib/net/packets.js
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,6 @@ var utils = require('../utils/utils');
|
|||||||
var crypto = require('../crypto/crypto');
|
var crypto = require('../crypto/crypto');
|
||||||
var assert = utils.assert;
|
var assert = utils.assert;
|
||||||
var constants = require('../protocol/constants');
|
var constants = require('../protocol/constants');
|
||||||
var BufferReader = require('../utils/reader');
|
|
||||||
var packets = require('./packets');
|
var packets = require('./packets');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,7 +39,7 @@ function Parser(options) {
|
|||||||
this.pending = [];
|
this.pending = [];
|
||||||
this.total = 0;
|
this.total = 0;
|
||||||
this.waiting = 24;
|
this.waiting = 24;
|
||||||
this.packet = null;
|
this.header = null;
|
||||||
|
|
||||||
this._init();
|
this._init();
|
||||||
}
|
}
|
||||||
@ -60,13 +59,13 @@ Parser.prototype._init = function _init(str) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
this.bip151.on('packet', function(cmd, body) {
|
this.bip151.on('packet', function(cmd, body) {
|
||||||
var packet = new Packet(cmd, body.length);
|
var payload;
|
||||||
try {
|
try {
|
||||||
packet.payload = self.parsePayload(cmd, body);
|
payload = self.parsePayload(cmd, body);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return self._error(e);
|
return self.error(e);
|
||||||
}
|
}
|
||||||
self.emit('packet', packet);
|
self.emit('packet', payload);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -76,7 +75,7 @@ Parser.prototype._init = function _init(str) {
|
|||||||
* @param {String} str
|
* @param {String} str
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Parser.prototype._error = function _error(str) {
|
Parser.prototype.error = function error(str) {
|
||||||
this.emit('error', new Error(str));
|
this.emit('error', new Error(str));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -120,42 +119,37 @@ Parser.prototype.feed = function feed(data) {
|
|||||||
* @param {Buffer} chunk
|
* @param {Buffer} chunk
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Parser.prototype.parse = function parse(chunk) {
|
Parser.prototype.parse = function parse(data) {
|
||||||
var checksum;
|
var payload, checksum;
|
||||||
|
|
||||||
if (chunk.length > constants.MAX_MESSAGE) {
|
assert(data.length <= constants.MAX_MESSAGE);
|
||||||
this.waiting = 24;
|
|
||||||
this.packet = null;
|
|
||||||
return this._error('Packet too large: %dmb.', utils.mb(chunk.length));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.packet) {
|
if (!this.header) {
|
||||||
this.packet = this.parseHeader(chunk);
|
this.header = this.parseHeader(data);
|
||||||
|
this.waiting = this.header.size;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.packet.payload = chunk;
|
checksum = crypto.checksum(data).readUInt32LE(0, true);
|
||||||
|
|
||||||
checksum = crypto.checksum(this.packet.payload).readUInt32LE(0, true);
|
if (checksum !== this.header.checksum) {
|
||||||
|
|
||||||
if (checksum !== this.packet.checksum) {
|
|
||||||
this.waiting = 24;
|
this.waiting = 24;
|
||||||
this.packet = null;
|
this.header = null;
|
||||||
return this._error('Invalid checksum');
|
return this.error('Invalid checksum');
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.packet.payload = this.parsePayload(this.packet.cmd, this.packet.payload);
|
payload = this.parsePayload(this.header.cmd, data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.emit('error', e);
|
this.emit('error', e);
|
||||||
this.waiting = 24;
|
this.waiting = 24;
|
||||||
this.packet = null;
|
this.header = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emit('packet', this.packet);
|
this.emit('packet', payload);
|
||||||
this.waiting = 24;
|
this.waiting = 24;
|
||||||
this.packet = null;
|
this.header = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -166,31 +160,31 @@ Parser.prototype.parse = function parse(chunk) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Parser.prototype.parseHeader = function parseHeader(h) {
|
Parser.prototype.parseHeader = function parseHeader(h) {
|
||||||
var i, magic, cmd, chk;
|
var i, magic, cmd, size, checksum;
|
||||||
|
|
||||||
magic = h.readUInt32LE(0, true);
|
magic = h.readUInt32LE(0, true);
|
||||||
|
|
||||||
if (magic !== this.network.magic)
|
if (magic !== this.network.magic)
|
||||||
return this._error('Invalid magic value: ' + magic.toString(16));
|
return this.error('Invalid magic value: ' + magic.toString(16));
|
||||||
|
|
||||||
// Count length of the cmd
|
// Count length of the cmd
|
||||||
for (i = 0; h[i + 4] !== 0 && i < 12; i++);
|
for (i = 0; h[i + 4] !== 0 && i < 12; i++);
|
||||||
|
|
||||||
if (i === 12)
|
if (i === 12)
|
||||||
return this._error('Not NULL-terminated cmd');
|
return this.error('Not NULL-terminated cmd');
|
||||||
|
|
||||||
cmd = h.toString('ascii', 4, 4 + i);
|
cmd = h.toString('ascii', 4, 4 + i);
|
||||||
|
|
||||||
this.waiting = h.readUInt32LE(16, true);
|
size = h.readUInt32LE(16, true);
|
||||||
|
|
||||||
if (this.waiting > constants.MAX_MESSAGE) {
|
if (size > constants.MAX_MESSAGE) {
|
||||||
this.waiting = 24;
|
this.waiting = 24;
|
||||||
return this._error('Packet length too large: %dmb', utils.mb(this.waiting));
|
return this.error('Packet length too large: %dmb', utils.mb(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
chk = h.readUInt32LE(20, true);
|
checksum = h.readUInt32LE(20, true);
|
||||||
|
|
||||||
return new Packet(cmd, this.waiting, chk);
|
return new Header(cmd, size, checksum);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -201,156 +195,16 @@ Parser.prototype.parseHeader = function parseHeader(h) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Parser.prototype.parsePayload = function parsePayload(cmd, data) {
|
Parser.prototype.parsePayload = function parsePayload(cmd, data) {
|
||||||
switch (cmd) {
|
return packets.fromRaw(cmd, data);
|
||||||
case 'version':
|
|
||||||
return packets.VersionPacket.fromRaw(data);
|
|
||||||
case 'verack':
|
|
||||||
return null;
|
|
||||||
case 'ping':
|
|
||||||
return parsePing(data);
|
|
||||||
case 'pong':
|
|
||||||
return parsePing(data);
|
|
||||||
case 'alert':
|
|
||||||
return packets.AlertPacket.fromRaw(data);
|
|
||||||
case 'getaddr':
|
|
||||||
return null;
|
|
||||||
case 'addr':
|
|
||||||
return parseAddr(data);
|
|
||||||
case 'inv':
|
|
||||||
return parseInv(data);
|
|
||||||
case 'getdata':
|
|
||||||
return parseInv(data);
|
|
||||||
case 'notfound':
|
|
||||||
return parseInv(data);
|
|
||||||
case 'getblocks':
|
|
||||||
return packets.GetBlocksPacket.fromRaw(data);
|
|
||||||
case 'getheaders':
|
|
||||||
return packets.GetBlocksPacket.fromRaw(data);
|
|
||||||
case 'headers':
|
|
||||||
return parseHeaders(data);
|
|
||||||
case 'sendheaders':
|
|
||||||
return null;
|
|
||||||
case 'block':
|
|
||||||
return bcoin.memblock.fromRaw(data);
|
|
||||||
case 'tx':
|
|
||||||
return bcoin.tx.fromRaw(data);
|
|
||||||
case 'reject':
|
|
||||||
return packets.RejectPacket.fromRaw(data);
|
|
||||||
case 'mempool':
|
|
||||||
return null;
|
|
||||||
case 'filterload':
|
|
||||||
return bcoin.bloom.fromRaw(data);
|
|
||||||
case 'filteradd':
|
|
||||||
return parseFilterAdd(data);
|
|
||||||
case 'filterclear':
|
|
||||||
return null;
|
|
||||||
case 'merkleblock':
|
|
||||||
return bcoin.merkleblock.fromRaw(data);
|
|
||||||
case 'getutxos':
|
|
||||||
return packets.GetUTXOsPacket.fromRaw(data);
|
|
||||||
case 'utxos':
|
|
||||||
return packets.UTXOsPacket.fromRaw(data);
|
|
||||||
case 'havewitness':
|
|
||||||
return null;
|
|
||||||
case 'feefilter':
|
|
||||||
return parseFeeFilter(data);
|
|
||||||
case 'sendcmpct':
|
|
||||||
return bcoin.bip152.SendCompact.fromRaw(data);
|
|
||||||
case 'cmpctblock':
|
|
||||||
return bcoin.bip152.CompactBlock.fromRaw(data);
|
|
||||||
case 'getblocktxn':
|
|
||||||
return bcoin.bip152.TXRequest.fromRaw(data);
|
|
||||||
case 'blocktxn':
|
|
||||||
return bcoin.bip152.TXResponse.fromRaw(data);
|
|
||||||
case 'encinit':
|
|
||||||
assert(data.length >= 34);
|
|
||||||
return data;
|
|
||||||
case 'encack':
|
|
||||||
assert(data.length >= 33);
|
|
||||||
return data;
|
|
||||||
case 'authchallenge':
|
|
||||||
assert(data.length >= 32);
|
|
||||||
return data;
|
|
||||||
case 'authreply':
|
|
||||||
assert(data.length >= 64);
|
|
||||||
return data;
|
|
||||||
case 'authpropose':
|
|
||||||
assert(data.length >= 32);
|
|
||||||
return data;
|
|
||||||
default:
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Helpers
|
|
||||||
*/
|
|
||||||
|
|
||||||
function parsePing(data) {
|
|
||||||
var p = new BufferReader(data);
|
|
||||||
return p.readU64();
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseInv(data) {
|
|
||||||
var p = new BufferReader(data);
|
|
||||||
var items = [];
|
|
||||||
var i, count;
|
|
||||||
|
|
||||||
count = p.readVarint();
|
|
||||||
|
|
||||||
assert(count <= 50000, 'Item count too high.');
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
items.push(bcoin.invitem.fromRaw(p));
|
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseHeaders(data) {
|
|
||||||
var p = new BufferReader(data);
|
|
||||||
var headers = [];
|
|
||||||
var i, count;
|
|
||||||
|
|
||||||
count = p.readVarint();
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
headers.push(bcoin.headers.fromRaw(p));
|
|
||||||
|
|
||||||
return headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseAddr(data) {
|
|
||||||
var p = new BufferReader(data);
|
|
||||||
var addrs = [];
|
|
||||||
var i, count;
|
|
||||||
|
|
||||||
count = p.readVarint();
|
|
||||||
|
|
||||||
assert(count <= 10000, 'Too many addresses.');
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
|
||||||
addrs.push(packets.NetworkAddress.fromRaw(p, true));
|
|
||||||
|
|
||||||
return addrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseFeeFilter(data) {
|
|
||||||
var p = new BufferReader(data);
|
|
||||||
return p.read64N();
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseFilterAdd(data) {
|
|
||||||
var p = new BufferReader(data);
|
|
||||||
return p.readVarBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Packet
|
* Packet
|
||||||
* @constructor
|
* @constructor
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function Packet(cmd, size, checksum) {
|
function Header(cmd, size, checksum) {
|
||||||
this.cmd = cmd;
|
this.cmd = cmd;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.checksum = checksum;
|
this.checksum = checksum;
|
||||||
|
|||||||
396
lib/net/peer.js
396
lib/net/peer.js
@ -12,14 +12,12 @@ var EventEmitter = require('events').EventEmitter;
|
|||||||
var utils = require('../utils/utils');
|
var utils = require('../utils/utils');
|
||||||
var Parser = require('./parser');
|
var Parser = require('./parser');
|
||||||
var Framer = require('./framer');
|
var Framer = require('./framer');
|
||||||
|
var packets = require('./packets');
|
||||||
|
var packetTypes = packets.types;
|
||||||
|
var NetworkAddress = require('../primitives/netaddress');
|
||||||
var assert = utils.assert;
|
var assert = utils.assert;
|
||||||
var constants = bcoin.constants;
|
var constants = bcoin.constants;
|
||||||
var InvItem = bcoin.invitem;
|
var InvItem = bcoin.invitem;
|
||||||
var VersionPacket = bcoin.packets.VersionPacket;
|
|
||||||
var GetBlocksPacket = bcoin.packets.GetBlocksPacket;
|
|
||||||
var RejectPacket = bcoin.packets.RejectPacket;
|
|
||||||
var NetworkAddress = bcoin.packets.NetworkAddress;
|
|
||||||
var GetUTXOsPacket = bcoin.packets.GetUTXOsPacket;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a remote peer.
|
* Represents a remote peer.
|
||||||
@ -225,7 +223,7 @@ Peer.prototype._init = function init() {
|
|||||||
});
|
});
|
||||||
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);
|
||||||
self.write(self.framer.encack(self.bip151.toRekey()));
|
self.send(self.bip151.toRekey());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,7 +266,7 @@ Peer.prototype._onConnect = function _onConnect() {
|
|||||||
if (this.bip151) {
|
if (this.bip151) {
|
||||||
assert(!this.bip151.completed);
|
assert(!this.bip151.completed);
|
||||||
this.logger.info('Attempting BIP151 handshake (%s).', this.hostname);
|
this.logger.info('Attempting BIP151 handshake (%s).', this.hostname);
|
||||||
this.write(this.framer.encinit(this.bip151.toEncinit()));
|
this.send(this.bip151.toEncinit());
|
||||||
return this.bip151.wait(3000, function(err) {
|
return this.bip151.wait(3000, function(err) {
|
||||||
if (err)
|
if (err)
|
||||||
self.error(err, true);
|
self.error(err, true);
|
||||||
@ -306,7 +304,7 @@ Peer.prototype._onBIP151 = function _onBIP151() {
|
|||||||
if (this.bip150.outbound) {
|
if (this.bip150.outbound) {
|
||||||
if (!this.bip150.peerIdentity)
|
if (!this.bip150.peerIdentity)
|
||||||
return this.error('No known identity for peer.');
|
return this.error('No known identity for peer.');
|
||||||
this.write(this.framer.authChallenge(this.bip150.toChallenge()));
|
this.send(this.bip150.toChallenge());
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.bip150.wait(3000, function(err) {
|
return this.bip150.wait(3000, function(err) {
|
||||||
@ -348,7 +346,7 @@ Peer.prototype._onHandshake = function _onHandshake() {
|
|||||||
if (this.pool.address.host !== '0.0.0.0'
|
if (this.pool.address.host !== '0.0.0.0'
|
||||||
&& !this.options.selfish
|
&& !this.options.selfish
|
||||||
&& this.pool.server) {
|
&& this.pool.server) {
|
||||||
this.write(this.framer.addr([this.pool.address]));
|
this.send(new packets.AddrPacket([this.pool.address]));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -384,7 +382,7 @@ Peer.prototype._onAck = function _onAck(err) {
|
|||||||
// Ask for headers-only.
|
// Ask for headers-only.
|
||||||
if (this.options.headers) {
|
if (this.options.headers) {
|
||||||
if (this.version.version >= 70012)
|
if (this.version.version >= 70012)
|
||||||
this.write(this.framer.sendHeaders());
|
this.send(new packets.SendHeadersPacket());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let them know we support segwit (old
|
// Let them know we support segwit (old
|
||||||
@ -392,7 +390,7 @@ Peer.prototype._onAck = function _onAck(err) {
|
|||||||
// of service bits).
|
// of service bits).
|
||||||
if (this.options.witness && this.network.oldWitness) {
|
if (this.options.witness && this.network.oldWitness) {
|
||||||
if (this.version.version >= 70012)
|
if (this.version.version >= 70012)
|
||||||
this.write(this.framer.haveWitness());
|
this.send(new packets.HaveWitnessPacket());
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want compact blocks!
|
// We want compact blocks!
|
||||||
@ -402,7 +400,7 @@ Peer.prototype._onAck = function _onAck(err) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Find some more peers.
|
// Find some more peers.
|
||||||
this.write(this.framer.getAddr());
|
this.write(new packets.GetAddrPacket());
|
||||||
|
|
||||||
// Relay our spv filter if we have one.
|
// Relay our spv filter if we have one.
|
||||||
this.updateWatch();
|
this.updateWatch();
|
||||||
@ -564,7 +562,7 @@ Peer.prototype.sendInv = function sendInv(items) {
|
|||||||
|
|
||||||
for (i = 0; i < items.length; i += 50000) {
|
for (i = 0; i < items.length; i += 50000) {
|
||||||
chunk = items.slice(i, i + 50000);
|
chunk = items.slice(i, i + 50000);
|
||||||
this.write(this.framer.inv(chunk));
|
this.send(new packets.InvPacket(chunk));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -593,16 +591,25 @@ Peer.prototype.sendHeaders = function sendHeaders(items) {
|
|||||||
|
|
||||||
for (i = 0; i < items.length; i += 2000) {
|
for (i = 0; i < items.length; i += 2000) {
|
||||||
chunk = items.slice(i, i + 2000);
|
chunk = items.slice(i, i + 2000);
|
||||||
this.write(this.framer.headers(chunk));
|
this.send(new packets.HeadersPacket(chunk));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a packet.
|
||||||
|
* @param {Packet} packet
|
||||||
|
*/
|
||||||
|
|
||||||
|
Peer.prototype.send = function send(packet) {
|
||||||
|
this.write(this.framer.packet(packet.cmd, packet.toRaw()));
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a `version` packet.
|
* Send a `version` packet.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.sendVersion = function sendVersion() {
|
Peer.prototype.sendVersion = function sendVersion() {
|
||||||
var packet = new VersionPacket({
|
var packet = new packets.VersionPacket({
|
||||||
version: constants.VERSION,
|
version: constants.VERSION,
|
||||||
services: this.pool.services,
|
services: this.pool.services,
|
||||||
ts: bcoin.now(),
|
ts: bcoin.now(),
|
||||||
@ -613,8 +620,7 @@ Peer.prototype.sendVersion = function sendVersion() {
|
|||||||
height: this.chain.height,
|
height: this.chain.height,
|
||||||
relay: this.options.relay
|
relay: this.options.relay
|
||||||
});
|
});
|
||||||
|
this.send(packet);
|
||||||
this.write(this.framer.version(packet));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -626,7 +632,7 @@ Peer.prototype.sendPing = function sendPing() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.version.version <= 60000) {
|
if (this.version.version <= 60000) {
|
||||||
this.write(this.framer.ping());
|
this.send(new packets.PingPacket());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -638,7 +644,7 @@ Peer.prototype.sendPing = function sendPing() {
|
|||||||
this.lastPing = utils.ms();
|
this.lastPing = utils.ms();
|
||||||
this.challenge = utils.nonce();
|
this.challenge = utils.nonce();
|
||||||
|
|
||||||
this.write(this.framer.ping(this.challenge));
|
this.send(new packets.PingPacket(this.challenge));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -671,7 +677,7 @@ Peer.prototype.updateWatch = function updateWatch() {
|
|||||||
if (!this.options.spv)
|
if (!this.options.spv)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.write(this.framer.filterLoad(this.pool.spvFilter));
|
this.send(packets.FilterLoadPacket.fromFilter(this.pool.spvFilter));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -680,7 +686,7 @@ Peer.prototype.updateWatch = function updateWatch() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.sendFeeRate = function sendFeeRate(rate) {
|
Peer.prototype.sendFeeRate = function sendFeeRate(rate) {
|
||||||
this.write(this.framer.feeFilter(rate));
|
this.send(new packets.FeeFilterPacket(rate));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -847,7 +853,7 @@ Peer.prototype.getData = function getData(items) {
|
|||||||
data[i] = item;
|
data[i] = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.write(this.framer.getData(data));
|
this.send(new packets.GetDataPacket(data));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -857,123 +863,120 @@ Peer.prototype.getData = function getData(items) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._onPacket = function onPacket(packet) {
|
Peer.prototype._onPacket = function onPacket(packet) {
|
||||||
var cmd = packet.cmd;
|
|
||||||
var payload = packet.payload;
|
|
||||||
|
|
||||||
if (this.bip151
|
if (this.bip151
|
||||||
&& !this.bip151.completed
|
&& !this.bip151.completed
|
||||||
&& cmd !== 'encinit'
|
&& packet.type !== packetTypes.ENCINIT
|
||||||
&& cmd !== 'encack') {
|
&& packet.type !== packetTypes.ENCACK) {
|
||||||
this.bip151.complete(new Error('Message before handshake.'));
|
this.bip151.complete(new Error('Message before handshake.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.bip150
|
if (this.bip150
|
||||||
&& !this.bip150.completed
|
&& !this.bip150.completed
|
||||||
&& cmd !== 'authchallenge'
|
&& packet.type !== packetTypes.AUTHCHALLENGE
|
||||||
&& cmd !== 'authreply'
|
&& packet.type !== packetTypes.AUTHREPLY
|
||||||
&& cmd !== 'authpropose') {
|
&& packet.type !== packetTypes.AUTHPROPOSE) {
|
||||||
this.bip150.complete(new Error('Message before auth.'));
|
this.bip150.complete(new Error('Message before auth.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.lastBlock && cmd !== 'tx')
|
if (this.lastBlock && packet.type !== packetTypes.TX)
|
||||||
this._flushMerkle();
|
this._flushMerkle();
|
||||||
|
|
||||||
this.lastRecv = utils.ms();
|
this.lastRecv = utils.ms();
|
||||||
|
|
||||||
switch (cmd) {
|
switch (packet.type) {
|
||||||
case 'version':
|
case packetTypes.VERSION:
|
||||||
return this._handleVersion(payload);
|
return this._handleVersion(packet);
|
||||||
case 'verack':
|
case packetTypes.VERACK:
|
||||||
this.fire(cmd);
|
this.fire(packet.cmd);
|
||||||
break;
|
break;
|
||||||
case 'ping':
|
case packetTypes.PING:
|
||||||
return this._handlePing(payload);
|
return this._handlePing(packet);
|
||||||
case 'pong':
|
case packetTypes.PONG:
|
||||||
return this._handlePong(payload);
|
return this._handlePong(packet);
|
||||||
case 'alert':
|
case packetTypes.ALERT:
|
||||||
return this._handleAlert(payload);
|
return this._handleAlert(packet);
|
||||||
case 'getaddr':
|
case packetTypes.GETADDR:
|
||||||
return this._handleGetAddr();
|
return this._handleGetAddr();
|
||||||
case 'addr':
|
case packetTypes.ADDR:
|
||||||
return this._handleAddr(payload);
|
return this._handleAddr(packet);
|
||||||
case 'inv':
|
case packetTypes.INV:
|
||||||
return this._handleInv(payload);
|
return this._handleInv(packet);
|
||||||
case 'getdata':
|
case packetTypes.GETDATA:
|
||||||
return this._handleGetData(payload);
|
return this._handleGetData(packet);
|
||||||
case 'notfound':
|
case packetTypes.NOTFOUND:
|
||||||
this.fire(cmd, payload);
|
this.fire(packet.cmd, packet.items);
|
||||||
break;
|
break;
|
||||||
case 'getblocks':
|
case packetTypes.GETBLOCKS:
|
||||||
return this._handleGetBlocks(payload);
|
return this._handleGetBlocks(packet);
|
||||||
case 'getheaders':
|
case packetTypes.GETHEADERS:
|
||||||
return this._handleGetHeaders(payload);
|
return this._handleGetHeaders(packet);
|
||||||
case 'headers':
|
case packetTypes.HEADERS:
|
||||||
return this._handleHeaders(payload);
|
return this._handleHeaders(packet);
|
||||||
case 'sendheaders':
|
case packetTypes.SENDHEADERS:
|
||||||
this.preferHeaders = true;
|
this.preferHeaders = true;
|
||||||
this.fire(cmd);
|
this.fire(packet.cmd);
|
||||||
break;
|
break;
|
||||||
case 'block':
|
case packetTypes.BLOCK:
|
||||||
this.fire(cmd, payload);
|
this.fire(packet.cmd, packet.block);
|
||||||
break;
|
break;
|
||||||
case 'tx':
|
case packetTypes.TX:
|
||||||
if (this.lastBlock) {
|
if (this.lastBlock) {
|
||||||
if (this.lastBlock.hasTX(payload)) {
|
if (this.lastBlock.hasTX(packet.tx)) {
|
||||||
this.lastBlock.addTX(payload);
|
this.lastBlock.addTX(packet.tx);
|
||||||
if (--this.waiting === 0)
|
if (--this.waiting === 0)
|
||||||
this._flushMerkle();
|
this._flushMerkle();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.fire(cmd, payload);
|
this.fire(packet.cmd, packet.tx);
|
||||||
break;
|
break;
|
||||||
case 'reject':
|
case packetTypes.REJECT:
|
||||||
return this._handleReject(payload);
|
return this._handleReject(packet);
|
||||||
case 'mempool':
|
case packetTypes.MEMPOOL:
|
||||||
return this._handleMempool();
|
return this._handleMempool();
|
||||||
case 'filterload':
|
case packetTypes.FILTERLOAD:
|
||||||
return this._handleFilterLoad(payload);
|
return this._handleFilterLoad(packet);
|
||||||
case 'filteradd':
|
case packetTypes.FILTERADD:
|
||||||
return this._handleFilterAdd(payload);
|
return this._handleFilterAdd(packet);
|
||||||
case 'filterclear':
|
case packetTypes.FILTERCLEAR:
|
||||||
return this._handleFilterClear();
|
return this._handleFilterClear();
|
||||||
case 'merkleblock':
|
case packetTypes.MERKLEBLOCK:
|
||||||
payload.verifyPartial();
|
packet.block.verifyPartial();
|
||||||
this.lastBlock = payload;
|
this.lastBlock = packet.block;
|
||||||
this.waiting = payload.matches.length;
|
this.waiting = packet.block.matches.length;
|
||||||
if (this.waiting === 0)
|
if (this.waiting === 0)
|
||||||
this._flushMerkle();
|
this._flushMerkle();
|
||||||
break;
|
break;
|
||||||
case 'getutxos':
|
case packetTypes.GETUTXOS:
|
||||||
return this._handleGetUTXOs(payload);
|
return this._handleGetUTXOs(packet);
|
||||||
case 'utxos':
|
case packetTypes.UTXOS:
|
||||||
return this._handleUTXOs(payload);
|
return this._handleUTXOs(packet);
|
||||||
case 'havewitness':
|
case packetTypes.HAVEWITNESS:
|
||||||
this.haveWitness = true;
|
this.haveWitness = true;
|
||||||
this.fire(cmd);
|
this.fire(packet.cmd);
|
||||||
break;
|
break;
|
||||||
case 'feefilter':
|
case packetTypes.FEEFILTER:
|
||||||
return this._handleFeeFilter(payload);
|
return this._handleFeeFilter(packet);
|
||||||
case 'sendcmpct':
|
case packetTypes.SENDCMPCT:
|
||||||
return this._handleSendCmpct(payload);
|
return this._handleSendCmpct(packet);
|
||||||
case 'cmpctblock':
|
case packetTypes.CMPCTBLOCK:
|
||||||
return this._handleCmpctBlock(payload);
|
return this._handleCmpctBlock(packet);
|
||||||
case 'getblocktxn':
|
case packetTypes.GETBLOCKTXN:
|
||||||
return this._handleGetBlockTxn(payload);
|
return this._handleGetBlockTxn(packet);
|
||||||
case 'blocktxn':
|
case packetTypes.BLOCKTXN:
|
||||||
return this._handleBlockTxn(payload);
|
return this._handleBlockTxn(packet);
|
||||||
case 'encinit':
|
case packetTypes.ENCINIT:
|
||||||
return this._handleEncinit(payload);
|
return this._handleEncinit(packet);
|
||||||
case 'encack':
|
case packetTypes.ENCACK:
|
||||||
return this._handleEncack(payload);
|
return this._handleEncack(packet);
|
||||||
case 'authchallenge':
|
case packetTypes.AUTHCHALLENGE:
|
||||||
return this._handleAuthChallenge(payload);
|
return this._handleAuthChallenge(packet);
|
||||||
case 'authreply':
|
case packetTypes.AUTHREPLY:
|
||||||
return this._handleAuthReply(payload);
|
return this._handleAuthReply(packet);
|
||||||
case 'authpropose':
|
case packetTypes.AUTHPROPOSE:
|
||||||
return this._handleAuthPropose(payload);
|
return this._handleAuthPropose(packet);
|
||||||
default:
|
case packetTypes.UNKNOWN:
|
||||||
this.logger.warning('Unknown packet: %s.', cmd);
|
this.logger.warning('Unknown packet: %s.', packet.cmd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1008,13 +1011,13 @@ Peer.prototype.fire = function fire(cmd, payload) {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleFilterLoad = function _handleFilterLoad(filter) {
|
Peer.prototype._handleFilterLoad = function _handleFilterLoad(packet) {
|
||||||
if (!filter.isWithinConstraints()) {
|
if (!packet.isWithinConstraints()) {
|
||||||
this.setMisbehavior(100);
|
this.setMisbehavior(100);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.spvFilter = filter;
|
this.spvFilter = packet.toFilter();
|
||||||
this.relay = true;
|
this.relay = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1024,7 +1027,9 @@ Peer.prototype._handleFilterLoad = function _handleFilterLoad(filter) {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleFilterAdd = function _handleFilterAdd(data) {
|
Peer.prototype._handleFilterAdd = function _handleFilterAdd(packet) {
|
||||||
|
var data = packet.data;
|
||||||
|
|
||||||
if (data.length > constants.script.MAX_PUSH) {
|
if (data.length > constants.script.MAX_PUSH) {
|
||||||
this.setMisbehavior(100);
|
this.setMisbehavior(100);
|
||||||
return;
|
return;
|
||||||
@ -1055,7 +1060,9 @@ Peer.prototype._handleFilterClear = function _handleFilterClear() {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleFeeFilter = function _handleFeeFilter(rate) {
|
Peer.prototype._handleFeeFilter = function _handleFeeFilter(packet) {
|
||||||
|
var rate = packet.rate;
|
||||||
|
|
||||||
if (!(rate >= 0 && rate <= constants.MAX_MONEY)) {
|
if (!(rate >= 0 && rate <= constants.MAX_MONEY)) {
|
||||||
this.setMisbehavior(100);
|
this.setMisbehavior(100);
|
||||||
return;
|
return;
|
||||||
@ -1111,7 +1118,7 @@ Peer.prototype._handleGetUTXOs = function _handleGetUTXOs(payload) {
|
|||||||
if (payload.prevout.length > 15)
|
if (payload.prevout.length > 15)
|
||||||
return done();
|
return done();
|
||||||
|
|
||||||
utxos = new GetUTXOsPacket();
|
utxos = new packets.GetUTXOsPacket();
|
||||||
|
|
||||||
utils.forEachSerial(payload.prevout, function(prevout, next) {
|
utils.forEachSerial(payload.prevout, function(prevout, next) {
|
||||||
var hash = prevout.hash;
|
var hash = prevout.hash;
|
||||||
@ -1154,7 +1161,7 @@ Peer.prototype._handleGetUTXOs = function _handleGetUTXOs(payload) {
|
|||||||
utxos.height = self.chain.height;
|
utxos.height = self.chain.height;
|
||||||
utxos.tip = self.chain.tip.hash;
|
utxos.tip = self.chain.tip.hash;
|
||||||
|
|
||||||
self.write(self.framer.UTXOs(utxos));
|
self.send(new packets.UTXOsPacket(utxos));
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -1378,8 +1385,7 @@ Peer.prototype._handleVersion = function _handleVersion(version) {
|
|||||||
if (!version.relay)
|
if (!version.relay)
|
||||||
this.relay = false;
|
this.relay = false;
|
||||||
|
|
||||||
// ACK
|
this.send(new packets.VerackPacket());
|
||||||
this.write(this.framer.verack());
|
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.fire('version', version);
|
this.fire('version', version);
|
||||||
};
|
};
|
||||||
@ -1482,10 +1488,11 @@ Peer.prototype._getItem = function _getItem(item, callback) {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleGetData = function _handleGetData(items) {
|
Peer.prototype._handleGetData = function _handleGetData(packet) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var notFound = [];
|
var notFound = [];
|
||||||
var unlock = this._lock(_handleGetData, [items, utils.nop]);
|
var items = packet.items;
|
||||||
|
var unlock = this._lock(_handleGetData, [packet, utils.nop]);
|
||||||
|
|
||||||
if (!unlock)
|
if (!unlock)
|
||||||
return;
|
return;
|
||||||
@ -1528,10 +1535,7 @@ Peer.prototype._handleGetData = function _handleGetData(items) {
|
|||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.hasWitness())
|
self.send(new packets.TXPacket(tx, item.hasWitness()));
|
||||||
self.write(self.framer.witnessTX(tx));
|
|
||||||
else
|
|
||||||
self.write(self.framer.tx(tx));
|
|
||||||
|
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
@ -1541,10 +1545,7 @@ Peer.prototype._handleGetData = function _handleGetData(items) {
|
|||||||
switch (item.type) {
|
switch (item.type) {
|
||||||
case constants.inv.BLOCK:
|
case constants.inv.BLOCK:
|
||||||
case constants.inv.WITNESS_BLOCK:
|
case constants.inv.WITNESS_BLOCK:
|
||||||
if (item.hasWitness())
|
self.send(new packets.BlockPacket(block, item.hasWitness()));
|
||||||
self.write(self.framer.witnessBlock(block));
|
|
||||||
else
|
|
||||||
self.write(self.framer.block(block));
|
|
||||||
break;
|
break;
|
||||||
case constants.inv.FILTERED_BLOCK:
|
case constants.inv.FILTERED_BLOCK:
|
||||||
case constants.inv.WITNESS_FILTERED_BLOCK:
|
case constants.inv.WITNESS_FILTERED_BLOCK:
|
||||||
@ -1555,22 +1556,18 @@ Peer.prototype._handleGetData = function _handleGetData(items) {
|
|||||||
|
|
||||||
block = block.toMerkle(self.spvFilter);
|
block = block.toMerkle(self.spvFilter);
|
||||||
|
|
||||||
self.write(self.framer.merkleBlock(block));
|
self.send(new packets.MerkleBlockPacket(block));
|
||||||
|
|
||||||
for (i = 0; i < block.txs.length; i++) {
|
for (i = 0; i < block.txs.length; i++) {
|
||||||
tx = block.txs[i];
|
tx = block.txs[i];
|
||||||
|
self.send(new packets.TXPacket(tx, item.hasWitness()));
|
||||||
if (item.hasWitness())
|
|
||||||
self.write(self.framer.witnessTX(tx));
|
|
||||||
else
|
|
||||||
self.write(self.framer.tx(tx));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case constants.inv.CMPCT_BLOCK:
|
case constants.inv.CMPCT_BLOCK:
|
||||||
// Fallback to full block.
|
// Fallback to full block.
|
||||||
if (block.height < self.chain.tip.height - 10) {
|
if (block.height < self.chain.tip.height - 10) {
|
||||||
self.write(self.framer.block(block));
|
self.send(new packets.BlockPacket(block, false));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1585,7 +1582,7 @@ Peer.prototype._handleGetData = function _handleGetData(items) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.write(self.framer.cmpctBlock(block));
|
self.send(new packets.CmpctBlockPacket(block, false));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
self.logger.warning(
|
self.logger.warning(
|
||||||
@ -1614,7 +1611,7 @@ Peer.prototype._handleGetData = function _handleGetData(items) {
|
|||||||
self.hostname);
|
self.hostname);
|
||||||
|
|
||||||
if (notFound.length > 0)
|
if (notFound.length > 0)
|
||||||
self.write(self.framer.notFound(notFound));
|
self.send(new packets.NotFoundPacket(notFound));
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -1626,7 +1623,8 @@ Peer.prototype._handleGetData = function _handleGetData(items) {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleAddr = function _handleAddr(addrs) {
|
Peer.prototype._handleAddr = function _handleAddr(packet) {
|
||||||
|
var addrs = packet.items;
|
||||||
var i;
|
var i;
|
||||||
|
|
||||||
for (i = 0; i < addrs.length; i++)
|
for (i = 0; i < addrs.length; i++)
|
||||||
@ -1648,8 +1646,8 @@ Peer.prototype._handleAddr = function _handleAddr(addrs) {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handlePing = function _handlePing(nonce) {
|
Peer.prototype._handlePing = function _handlePing(packet) {
|
||||||
this.write(this.framer.pong(nonce));
|
this.send(new packets.PongPacket(packet.nonce));
|
||||||
this.fire('ping', this.minPing);
|
this.fire('ping', this.minPing);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1659,7 +1657,8 @@ Peer.prototype._handlePing = function _handlePing(nonce) {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handlePong = function _handlePong(nonce) {
|
Peer.prototype._handlePong = function _handlePong(packet) {
|
||||||
|
var nonce = packet.nonce;
|
||||||
var now = utils.ms();
|
var now = utils.ms();
|
||||||
|
|
||||||
if (!this.challenge) {
|
if (!this.challenge) {
|
||||||
@ -1734,7 +1733,7 @@ Peer.prototype._handleGetAddr = function _handleGetAddr() {
|
|||||||
items.length,
|
items.length,
|
||||||
this.hostname);
|
this.hostname);
|
||||||
|
|
||||||
this.write(this.framer.addr(items));
|
this.send(new packets.AddrPacket(items));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1743,10 +1742,12 @@ Peer.prototype._handleGetAddr = function _handleGetAddr() {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleInv = function _handleInv(items) {
|
Peer.prototype._handleInv = function _handleInv(packet) {
|
||||||
|
var items = packet.items;
|
||||||
var blocks = [];
|
var blocks = [];
|
||||||
var txs = [];
|
var txs = [];
|
||||||
var i, item, unknown;
|
var unknown = -1;
|
||||||
|
var i, item;
|
||||||
|
|
||||||
if (items.length > 50000) {
|
if (items.length > 50000) {
|
||||||
this.setMisbehavior(100);
|
this.setMisbehavior(100);
|
||||||
@ -1755,13 +1756,16 @@ Peer.prototype._handleInv = function _handleInv(items) {
|
|||||||
|
|
||||||
for (i = 0; i < items.length; i++) {
|
for (i = 0; i < items.length; i++) {
|
||||||
item = items[i];
|
item = items[i];
|
||||||
if (item.type === constants.inv.TX) {
|
switch (item.type) {
|
||||||
txs.push(item.hash);
|
case constants.inv.TX:
|
||||||
} else if (item.type === constants.inv.BLOCK) {
|
txs.push(item.hash);
|
||||||
blocks.push(item.hash);
|
break;
|
||||||
} else {
|
case constants.inv.BLOCK:
|
||||||
unknown = item.type;
|
blocks.push(item.hash);
|
||||||
continue;
|
break;
|
||||||
|
default:
|
||||||
|
unknown = item.type;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
this.invFilter.add(item.hash, 'hex');
|
this.invFilter.add(item.hash, 'hex');
|
||||||
}
|
}
|
||||||
@ -1774,7 +1778,7 @@ Peer.prototype._handleInv = function _handleInv(items) {
|
|||||||
if (txs.length > 0)
|
if (txs.length > 0)
|
||||||
this.emit('txs', txs);
|
this.emit('txs', txs);
|
||||||
|
|
||||||
if (unknown != null) {
|
if (unknown !== -1) {
|
||||||
this.logger.warning(
|
this.logger.warning(
|
||||||
'Peer sent an unknown inv type: %d (%s).',
|
'Peer sent an unknown inv type: %d (%s).',
|
||||||
unknown, this.hostname);
|
unknown, this.hostname);
|
||||||
@ -1787,7 +1791,8 @@ Peer.prototype._handleInv = function _handleInv(items) {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleHeaders = function _handleHeaders(headers) {
|
Peer.prototype._handleHeaders = function _handleHeaders(packet) {
|
||||||
|
var headers = packet.items;
|
||||||
if (headers.length > 2000) {
|
if (headers.length > 2000) {
|
||||||
this.setMisbehavior(100);
|
this.setMisbehavior(100);
|
||||||
return;
|
return;
|
||||||
@ -1835,20 +1840,20 @@ Peer.prototype._handleAlert = function _handleAlert(alert) {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleEncinit = function _handleEncinit(data) {
|
Peer.prototype._handleEncinit = function _handleEncinit(packet) {
|
||||||
if (!this.bip151)
|
if (!this.bip151)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.bip151.encinit(data);
|
this.bip151.encinit(packet.publicKey, packet.cipher);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.error(e);
|
this.error(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.write(this.framer.encack(this.bip151.toEncack()));
|
this.send(this.bip151.toEncack());
|
||||||
|
|
||||||
this.fire('encinit', data);
|
this.fire('encinit', packet);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1857,18 +1862,18 @@ Peer.prototype._handleEncinit = function _handleEncinit(data) {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleEncack = function _handleEncack(data) {
|
Peer.prototype._handleEncack = function _handleEncack(packet) {
|
||||||
if (!this.bip151)
|
if (!this.bip151)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.bip151.encack(data);
|
this.bip151.encack(packet.publicKey);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.error(e);
|
this.error(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fire('encack', data);
|
this.fire('encack', packet);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1877,22 +1882,22 @@ Peer.prototype._handleEncack = function _handleEncack(data) {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleAuthChallenge = function _handleAuthChallenge(data) {
|
Peer.prototype._handleAuthChallenge = function _handleAuthChallenge(packet) {
|
||||||
var result;
|
var sig;
|
||||||
|
|
||||||
if (!this.bip150)
|
if (!this.bip150)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result = this.bip150.challenge(data);
|
sig = this.bip150.challenge(packet.hash);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.error(e);
|
this.error(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.write(this.framer.authReply(result));
|
this.send(new packets.AuthReplyPacket(sig));
|
||||||
|
|
||||||
this.fire('authchallenge', data);
|
this.fire('authchallenge', packet.hash);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1901,23 +1906,23 @@ Peer.prototype._handleAuthChallenge = function _handleAuthChallenge(data) {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleAuthReply = function _handleAuthReply(data) {
|
Peer.prototype._handleAuthReply = function _handleAuthReply(packet) {
|
||||||
var result;
|
var hash;
|
||||||
|
|
||||||
if (!this.bip150)
|
if (!this.bip150)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result = this.bip150.reply(data);
|
hash = this.bip150.reply(packet.signature);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.error(e);
|
this.error(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
if (hash)
|
||||||
this.write(this.framer.authPropose(result));
|
this.send(new packets.AuthProposePacket(hash));
|
||||||
|
|
||||||
this.fire('authreply', data);
|
this.fire('authreply', packet.signature);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1926,22 +1931,22 @@ Peer.prototype._handleAuthReply = function _handleAuthReply(data) {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleAuthPropose = function _handleAuthPropose(data) {
|
Peer.prototype._handleAuthPropose = function _handleAuthPropose(packet) {
|
||||||
var result;
|
var hash;
|
||||||
|
|
||||||
if (!this.bip150)
|
if (!this.bip150)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result = this.bip150.propose(data);
|
hash = this.bip150.propose(packet.hash);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.error(e);
|
this.error(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.write(this.framer.authChallenge(result));
|
this.send(new packets.AuthChallengePacket(hash));
|
||||||
|
|
||||||
this.fire('authpropose', data);
|
this.fire('authpropose', packet.hash);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1950,25 +1955,25 @@ Peer.prototype._handleAuthPropose = function _handleAuthPropose(data) {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleSendCmpct = function _handleSendCmpct(cmpct) {
|
Peer.prototype._handleSendCmpct = function _handleSendCmpct(packet) {
|
||||||
if (cmpct.version !== 1) {
|
if (packet.version !== 1) {
|
||||||
// Ignore
|
// Ignore
|
||||||
this.logger.info('Peer request compact blocks version %d (%s).',
|
this.logger.info('Peer request compact blocks version %d (%s).',
|
||||||
cmpct.version, this.hostname);
|
packet.version, this.hostname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmpct.mode !== 0) {
|
if (packet.mode !== 0) {
|
||||||
// Ignore (we can't do mode 1 yet).
|
// Ignore (we can't do mode 1 yet).
|
||||||
this.logger.info('Peer request compact blocks mode %d (%s).',
|
this.logger.info('Peer request compact blocks mode %d (%s).',
|
||||||
cmpct.mode, this.hostname);
|
packet.mode, this.hostname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.info('Peer initialized compact blocks (%s).', this.hostname);
|
this.logger.info('Peer initialized compact blocks (%s).', this.hostname);
|
||||||
|
|
||||||
this.compactMode = cmpct;
|
this.compactMode = packet;
|
||||||
this.fire('sendcmpct', cmpct);
|
this.fire('sendcmpct', packet);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1977,8 +1982,9 @@ Peer.prototype._handleSendCmpct = function _handleSendCmpct(cmpct) {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleCmpctBlock = function _handleCmpctBlock(block) {
|
Peer.prototype._handleCmpctBlock = function _handleCmpctBlock(packet) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
var block = packet.block;
|
||||||
var hash = block.hash('hex');
|
var hash = block.hash('hex');
|
||||||
var result;
|
var result;
|
||||||
|
|
||||||
@ -2013,7 +2019,7 @@ Peer.prototype._handleCmpctBlock = function _handleCmpctBlock(block) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.write(this.framer.getBlockTxn(block.toRequest()));
|
this.send(block.toRequest());
|
||||||
|
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
'Received semi-full compact block %s (%s).',
|
'Received semi-full compact block %s (%s).',
|
||||||
@ -2033,8 +2039,9 @@ Peer.prototype._handleCmpctBlock = function _handleCmpctBlock(block) {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleGetBlockTxn = function _handleGetBlockTxn(req) {
|
Peer.prototype._handleGetBlockTxn = function _handleGetBlockTxn(packet) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
var req = packet.request;
|
||||||
var res, item;
|
var res, item;
|
||||||
|
|
||||||
function done(err) {
|
function done(err) {
|
||||||
@ -2077,7 +2084,7 @@ Peer.prototype._handleGetBlockTxn = function _handleGetBlockTxn(req) {
|
|||||||
|
|
||||||
res = bcoin.bip152.TXResponse.fromBlock(block, req);
|
res = bcoin.bip152.TXResponse.fromBlock(block, req);
|
||||||
|
|
||||||
self.write(self.framer.blockTxn(res));
|
self.send(new packets.BlockTxnPacket(res, false));
|
||||||
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -2089,7 +2096,8 @@ Peer.prototype._handleGetBlockTxn = function _handleGetBlockTxn(req) {
|
|||||||
* @param {Object}
|
* @param {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype._handleBlockTxn = function _handleBlockTxn(res) {
|
Peer.prototype._handleBlockTxn = function _handleBlockTxn(packet) {
|
||||||
|
var res = packet.response;
|
||||||
var block = this.compactBlocks[res.hash];
|
var block = this.compactBlocks[res.hash];
|
||||||
|
|
||||||
if (!block) {
|
if (!block) {
|
||||||
@ -2124,7 +2132,7 @@ Peer.prototype.sendAlert = function sendAlert(alert) {
|
|||||||
if (!this.invFilter.added(alert.hash()))
|
if (!this.invFilter.added(alert.hash()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.write(this.framer.alert(alert));
|
this.send(alert);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2135,7 +2143,7 @@ Peer.prototype.sendAlert = function sendAlert(alert) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.sendGetHeaders = function sendGetHeaders(locator, stop) {
|
Peer.prototype.sendGetHeaders = function sendGetHeaders(locator, stop) {
|
||||||
var packet = new GetBlocksPacket(locator, stop);
|
var packet = new packets.GetHeadersPacket(locator, stop);
|
||||||
var height = -1;
|
var height = -1;
|
||||||
var hash = null;
|
var hash = null;
|
||||||
|
|
||||||
@ -2153,7 +2161,7 @@ Peer.prototype.sendGetHeaders = function sendGetHeaders(locator, stop) {
|
|||||||
|
|
||||||
this.logger.debug('Height: %d, Hash: %s, Stop: %s', height, hash, stop);
|
this.logger.debug('Height: %d, Hash: %s, Stop: %s', height, hash, stop);
|
||||||
|
|
||||||
this.write(this.framer.getHeaders(packet));
|
this.send(packet);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2163,7 +2171,7 @@ Peer.prototype.sendGetHeaders = function sendGetHeaders(locator, stop) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.sendGetBlocks = function getBlocks(locator, stop) {
|
Peer.prototype.sendGetBlocks = function getBlocks(locator, stop) {
|
||||||
var packet = new GetBlocksPacket(locator, stop);
|
var packet = new packets.GetBlocksPacket(locator, stop);
|
||||||
var height = -1;
|
var height = -1;
|
||||||
var hash = null;
|
var hash = null;
|
||||||
|
|
||||||
@ -2181,7 +2189,7 @@ Peer.prototype.sendGetBlocks = function getBlocks(locator, stop) {
|
|||||||
|
|
||||||
this.logger.debug('Height: %d, Hash: %s, Stop: %s', height, hash, stop);
|
this.logger.debug('Height: %d, Hash: %s, Stop: %s', height, hash, stop);
|
||||||
|
|
||||||
this.write(this.framer.getBlocks(packet));
|
this.send(packet);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2203,7 +2211,7 @@ Peer.prototype.sendMempool = function sendMempool() {
|
|||||||
'Requesting inv packet from peer with mempool (%s).',
|
'Requesting inv packet from peer with mempool (%s).',
|
||||||
this.hostname);
|
this.hostname);
|
||||||
|
|
||||||
this.write(this.framer.mempool());
|
this.send(new packets.MempoolPacket());
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2212,7 +2220,7 @@ Peer.prototype.sendMempool = function sendMempool() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.sendReject = function sendReject(code, reason, obj) {
|
Peer.prototype.sendReject = function sendReject(code, reason, obj) {
|
||||||
var reject = RejectPacket.fromReason(code, reason, obj);
|
var reject = packets.RejectPacket.fromReason(code, reason, obj);
|
||||||
|
|
||||||
if (obj) {
|
if (obj) {
|
||||||
this.logger.debug('Rejecting %s %s (%s): ccode=%s reason=%s.',
|
this.logger.debug('Rejecting %s %s (%s): ccode=%s reason=%s.',
|
||||||
@ -2226,7 +2234,7 @@ Peer.prototype.sendReject = function sendReject(code, reason, obj) {
|
|||||||
'Sending reject packet to peer (%s).',
|
'Sending reject packet to peer (%s).',
|
||||||
this.hostname);
|
this.hostname);
|
||||||
|
|
||||||
this.write(this.framer.reject(reject));
|
this.send(reject);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2234,9 +2242,9 @@ Peer.prototype.sendReject = function sendReject(code, reason, obj) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Peer.prototype.sendCompact = function sendCompact() {
|
Peer.prototype.sendCompact = function sendCompact() {
|
||||||
var cmpct = new bcoin.bip152.SendCompact(0, 1);
|
var cmpct = new packets.SendCmpctPacket(0, 1);
|
||||||
this.logger.info('Initializing compact blocks (%s).', this.hostname);
|
this.logger.info('Initializing compact blocks (%s).', this.hostname);
|
||||||
this.write(this.framer.sendCmpct(cmpct));
|
this.send(cmpct);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -15,7 +15,7 @@ var IP = require('../utils/ip');
|
|||||||
var assert = utils.assert;
|
var assert = utils.assert;
|
||||||
var constants = bcoin.constants;
|
var constants = bcoin.constants;
|
||||||
var VerifyError = bcoin.errors.VerifyError;
|
var VerifyError = bcoin.errors.VerifyError;
|
||||||
var NetworkAddress = bcoin.packets.NetworkAddress;
|
var NetworkAddress = require('../primitives/netaddress');
|
||||||
var InvItem = bcoin.invitem;
|
var InvItem = bcoin.invitem;
|
||||||
var VerifyResult = utils.VerifyResult;
|
var VerifyResult = utils.VerifyResult;
|
||||||
|
|
||||||
|
|||||||
304
lib/primitives/netaddress.js
Normal file
304
lib/primitives/netaddress.js
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
/*!
|
||||||
|
* packets.js - packets for bcoin
|
||||||
|
* Copyright (c) 2014-2015, Fedor Indutny (MIT License)
|
||||||
|
* Copyright (c) 2014-2016, Christopher Jeffrey (MIT License).
|
||||||
|
* https://github.com/bcoin-org/bcoin
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var bcoin = require('../env');
|
||||||
|
var constants = require('../protocol/constants');
|
||||||
|
var utils = require('../utils/utils');
|
||||||
|
var IP = require('../utils/ip');
|
||||||
|
var assert = utils.assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a network address.
|
||||||
|
* @exports NetworkAddress
|
||||||
|
* @constructor
|
||||||
|
* @param {Object} options
|
||||||
|
* @param {Number?} options.ts - Timestamp.
|
||||||
|
* @param {Number?} options.services - Service bits.
|
||||||
|
* @param {String?} options.host - IP address (IPv6 or IPv4).
|
||||||
|
* @param {Number?} options.port - Port.
|
||||||
|
* @property {Number} id
|
||||||
|
* @property {Host} host
|
||||||
|
* @property {Number} port
|
||||||
|
* @property {Number} services
|
||||||
|
* @property {Number} ts
|
||||||
|
*/
|
||||||
|
|
||||||
|
function NetworkAddress(options) {
|
||||||
|
if (!(this instanceof NetworkAddress))
|
||||||
|
return new NetworkAddress(options);
|
||||||
|
|
||||||
|
this.id = NetworkAddress.uid++;
|
||||||
|
this.host = '0.0.0.0';
|
||||||
|
this.port = 0;
|
||||||
|
this.services = 0;
|
||||||
|
this.ts = 0;
|
||||||
|
this.hostname = '0.0.0.0:0';
|
||||||
|
|
||||||
|
if (options)
|
||||||
|
this.fromOptions(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Globally incremented unique id.
|
||||||
|
* @private
|
||||||
|
* @type {Number}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.uid = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject properties from options object.
|
||||||
|
* @private
|
||||||
|
* @param {Object} options
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.prototype.fromOptions = function fromOptions(options) {
|
||||||
|
var host = options.host;
|
||||||
|
|
||||||
|
assert(typeof options.host === 'string');
|
||||||
|
assert(typeof options.port === 'number');
|
||||||
|
|
||||||
|
if (IP.version(host) !== -1)
|
||||||
|
host = IP.normalize(host);
|
||||||
|
|
||||||
|
this.host = host;
|
||||||
|
this.port = options.port;
|
||||||
|
|
||||||
|
if (options.services) {
|
||||||
|
assert(typeof options.services === 'number');
|
||||||
|
this.services = options.services;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.ts) {
|
||||||
|
assert(typeof options.ts === 'number');
|
||||||
|
this.ts = options.ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hostname = IP.hostname(this.host, this.port);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate network address from options.
|
||||||
|
* @param {Object} options
|
||||||
|
* @returns {NetworkAddress}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.fromOptions = function fromOptions(options) {
|
||||||
|
return new NetworkAddress().fromOptions(options);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the `host` field is an ip address.
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.prototype.isIP = function isIP() {
|
||||||
|
return IP.version(this.host) !== -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the NETWORK service bit is set.
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.prototype.hasNetwork = function hasNetwork() {
|
||||||
|
return (this.services & constants.services.NETWORK) !== 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the BLOOM service bit is set.
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.prototype.hasBloom = function hasBloom() {
|
||||||
|
return (this.services & constants.services.BLOOM) !== 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the GETUTXO service bit is set.
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.prototype.hasUTXO = function hasUTXO() {
|
||||||
|
return (this.services & constants.services.GETUTXO) !== 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the WITNESS service bit is set.
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.prototype.hasWitness = function hasWitness() {
|
||||||
|
return (this.services & constants.services.WITNESS) !== 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set host.
|
||||||
|
* @param {String} host
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.prototype.setHost = function setHost(host) {
|
||||||
|
this.host = host;
|
||||||
|
this.hostname = IP.hostname(host, this.port);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set port.
|
||||||
|
* @param {Number} port
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.prototype.setPort = function setPort(port) {
|
||||||
|
this.port = port;
|
||||||
|
this.hostname = IP.hostname(this.host, port);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inspect the network address.
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.prototype.inspect = function inspect() {
|
||||||
|
return '<NetworkAddress:'
|
||||||
|
+ ' id=' + this.id
|
||||||
|
+ ' hostname=' + IP.hostname(this.host, this.port)
|
||||||
|
+ ' services=' + this.services.toString(2)
|
||||||
|
+ ' date=' + utils.date(this.ts)
|
||||||
|
+ '>';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject properties from hostname and network.
|
||||||
|
* @private
|
||||||
|
* @param {String} hostname
|
||||||
|
* @param {(Network|NetworkType)?} network
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.prototype.fromHostname = function fromHostname(hostname, network) {
|
||||||
|
var address = IP.parseHost(hostname);
|
||||||
|
|
||||||
|
network = bcoin.network.get(network);
|
||||||
|
|
||||||
|
this.host = address.host;
|
||||||
|
this.port = address.port || network.port;
|
||||||
|
this.services = constants.services.NETWORK
|
||||||
|
| constants.services.BLOOM
|
||||||
|
| constants.services.WITNESS;
|
||||||
|
this.ts = bcoin.now();
|
||||||
|
|
||||||
|
this.hostname = IP.hostname(this.host, this.port);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a network address
|
||||||
|
* from a hostname (i.e. 127.0.0.1:8333).
|
||||||
|
* @param {String} hostname
|
||||||
|
* @param {(Network|NetworkType)?} network
|
||||||
|
* @returns {NetworkAddress}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.fromHostname = function fromHostname(hostname, network) {
|
||||||
|
return new NetworkAddress().fromHostname(hostname, network);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject properties from socket.
|
||||||
|
* @private
|
||||||
|
* @param {net.Socket} socket
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.prototype.fromSocket = function fromSocket(socket) {
|
||||||
|
assert(typeof socket.remoteAddress === 'string');
|
||||||
|
assert(typeof socket.remotePort === 'number');
|
||||||
|
|
||||||
|
this.host = IP.normalize(socket.remoteAddress);
|
||||||
|
this.port = socket.remotePort;
|
||||||
|
this.services = constants.services.NETWORK
|
||||||
|
| constants.services.BLOOM
|
||||||
|
| constants.services.WITNESS;
|
||||||
|
this.ts = bcoin.now();
|
||||||
|
|
||||||
|
this.hostname = IP.hostname(this.host, this.port);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate a network address
|
||||||
|
* from a socket.
|
||||||
|
* @param {net.Socket} socket
|
||||||
|
* @returns {NetworkAddress}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.fromSocket = function fromSocket(hostname) {
|
||||||
|
return new NetworkAddress().fromSocket(hostname);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject properties from serialized data.
|
||||||
|
* @private
|
||||||
|
* @param {Buffer} data
|
||||||
|
* @param {Boolean?} full - Include timestamp.
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.prototype.fromRaw = function fromRaw(data, full) {
|
||||||
|
var p = bcoin.reader(data);
|
||||||
|
var now = bcoin.now();
|
||||||
|
|
||||||
|
// only version >= 31402
|
||||||
|
this.ts = full ? p.readU32() : 0;
|
||||||
|
this.services = p.readU53();
|
||||||
|
this.host = IP.toString(p.readBytes(16));
|
||||||
|
this.port = p.readU16BE();
|
||||||
|
|
||||||
|
if (this.ts <= 100000000 || this.ts > now + 10 * 60)
|
||||||
|
this.ts = now - 5 * 24 * 60 * 60;
|
||||||
|
|
||||||
|
this.hostname = IP.hostname(this.host, this.port);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insantiate a network address from serialized data.
|
||||||
|
* @param {Buffer} data
|
||||||
|
* @param {Boolean?} full - Include timestamp.
|
||||||
|
* @returns {NetworkAddress}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.fromRaw = function fromRaw(data, full) {
|
||||||
|
return new NetworkAddress().fromRaw(data, full);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize network address.
|
||||||
|
* @param {Boolean} full - Include timestamp.
|
||||||
|
* @returns {Buffer}
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetworkAddress.prototype.toRaw = function toRaw(full, writer) {
|
||||||
|
var p = bcoin.writer(writer);
|
||||||
|
|
||||||
|
if (full)
|
||||||
|
p.writeU32(this.ts);
|
||||||
|
|
||||||
|
p.writeU64(this.services);
|
||||||
|
p.writeBytes(IP.toBuffer(this.host));
|
||||||
|
p.writeU16BE(this.port);
|
||||||
|
|
||||||
|
if (!writer)
|
||||||
|
p = p.render();
|
||||||
|
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = NetworkAddress;
|
||||||
@ -631,6 +631,17 @@ exports.ZERO_HASH160 = new Buffer(
|
|||||||
'hex'
|
'hex'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A hash of all 0xff.
|
||||||
|
* @const {String}
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.MAX_HASH160 = new Buffer(
|
||||||
|
'ffffffffffffffffffffffffffffffffffffffff',
|
||||||
|
'hex'
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A hash of all zeroes.
|
* A hash of all zeroes.
|
||||||
* @const {String}
|
* @const {String}
|
||||||
@ -639,6 +650,14 @@ exports.ZERO_HASH160 = new Buffer(
|
|||||||
|
|
||||||
exports.NULL_HASH160 = '0000000000000000000000000000000000000000';
|
exports.NULL_HASH160 = '0000000000000000000000000000000000000000';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A hash of all 0xff.
|
||||||
|
* @const {String}
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.HIGH_HASH160 = 'ffffffffffffffffffffffffffffffffffffffff';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A compressed pubkey of all zeroes.
|
* A compressed pubkey of all zeroes.
|
||||||
* @const {Buffer}
|
* @const {Buffer}
|
||||||
@ -650,6 +669,31 @@ exports.ZERO_KEY = new Buffer(
|
|||||||
'hex'
|
'hex'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A 73 byte signature of all zeroes.
|
||||||
|
* @const {Buffer}
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.ZERO_SIG = new Buffer(''
|
||||||
|
+ '0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
|
+ '0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
|
+ '000000000000000000',
|
||||||
|
'hex'
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A 64 byte signature of all zeroes.
|
||||||
|
* @const {Buffer}
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.ZERO_SIG64 = new Buffer(''
|
||||||
|
+ '0000000000000000000000000000000000000000000000000000000000000000'
|
||||||
|
+ '0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
|
'hex'
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BCoin version.
|
* BCoin version.
|
||||||
* @const {String}
|
* @const {String}
|
||||||
|
|||||||
@ -8,10 +8,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var constants = require('../protocol/constants');
|
var constants = require('../protocol/constants');
|
||||||
var assert = require('assert');
|
var murmur3 = require('./murmur3');
|
||||||
var BufferReader = require('../utils/reader');
|
|
||||||
var BufferWriter = require('../utils/writer');
|
|
||||||
var murmur3 = require('../utils/murmur3');
|
|
||||||
var sum32 = murmur3.sum32;
|
var sum32 = murmur3.sum32;
|
||||||
var mul32 = murmur3.mul32;
|
var mul32 = murmur3.mul32;
|
||||||
|
|
||||||
@ -147,66 +144,6 @@ Bloom.prototype.added = function added(val, enc) {
|
|||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensure the filter is within the size limits.
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Bloom.prototype.isWithinConstraints = function isWithinConstraints() {
|
|
||||||
if (this.filter.length > constants.bloom.MAX_BLOOM_FILTER_SIZE)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (this.n > constants.bloom.MAX_HASH_FUNCS)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serialize the filter in `filterload` packet format.
|
|
||||||
* @returns {Buffer}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Bloom.prototype.toRaw = function toRaw(writer) {
|
|
||||||
var p = BufferWriter(writer);
|
|
||||||
|
|
||||||
p.writeVarBytes(this.filter);
|
|
||||||
p.writeU32(this.n);
|
|
||||||
p.writeU32(this.tweak);
|
|
||||||
p.writeU8(this.update);
|
|
||||||
|
|
||||||
if (!writer)
|
|
||||||
p = p.render();
|
|
||||||
|
|
||||||
return p;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate bloom filter from
|
|
||||||
* serialized data (filterload).
|
|
||||||
* @param {Buffer}
|
|
||||||
* @param {String?} enc
|
|
||||||
* @returns {Bloom}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Bloom.fromRaw = function fromRaw(data, enc) {
|
|
||||||
var p, filter, n, tweak, update;
|
|
||||||
|
|
||||||
if (typeof data === 'string')
|
|
||||||
data = new Buffer(data, enc);
|
|
||||||
|
|
||||||
p = BufferReader(data);
|
|
||||||
|
|
||||||
filter = p.readVarBytes();
|
|
||||||
n = p.readU32();
|
|
||||||
tweak = p.readU32();
|
|
||||||
update = p.readU8();
|
|
||||||
|
|
||||||
assert(constants.filterFlagsByVal[update] != null, 'Bad filter flag.');
|
|
||||||
|
|
||||||
return new Bloom(filter, n, tweak, update);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a filter from a false positive rate.
|
* Create a filter from a false positive rate.
|
||||||
* @param {Number} items - Expeected number of items.
|
* @param {Number} items - Expeected number of items.
|
||||||
@ -415,11 +352,15 @@ RollingFilter.prototype.added = function added(val, enc) {
|
|||||||
* Helpers
|
* Helpers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
function U64(hi, lo) {
|
||||||
|
this.hi = hi;
|
||||||
|
this.lo = lo;
|
||||||
|
}
|
||||||
|
|
||||||
function read(data, off) {
|
function read(data, off) {
|
||||||
return {
|
var hi = data.readUInt32LE(off + 4, true);
|
||||||
hi: data.readUInt32LE(off + 4, true),
|
var lo = data.readUInt32LE(off, true);
|
||||||
lo: data.readUInt32LE(off, true)
|
return new U64(hi, lo);
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function write(data, value, off) {
|
function write(data, value, off) {
|
||||||
@ -27,15 +27,17 @@ describe('BIP150', function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
it('should do encinit', function() {
|
it('should do encinit', function() {
|
||||||
client.encinit(server.toEncinit());
|
var init = server.toEncinit();
|
||||||
server.encinit(client.toEncinit());
|
client.encinit(init.publicKey, init.cipher);
|
||||||
|
var init = client.toEncinit();
|
||||||
|
server.encinit(init.publicKey, init.cipher);
|
||||||
assert(!client.handshake);
|
assert(!client.handshake);
|
||||||
assert(!server.handshake);
|
assert(!server.handshake);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should do encack', function() {
|
it('should do encack', function() {
|
||||||
client.encack(server.toEncack());
|
client.encack(server.toEncack().publicKey);
|
||||||
server.encack(client.toEncack());
|
server.encack(client.toEncack().publicKey);
|
||||||
assert(client.handshake);
|
assert(client.handshake);
|
||||||
assert(server.handshake);
|
assert(server.handshake);
|
||||||
});
|
});
|
||||||
@ -49,7 +51,7 @@ describe('BIP150', function() {
|
|||||||
|
|
||||||
it('should do BIP150 handshake', function() {
|
it('should do BIP150 handshake', function() {
|
||||||
var challenge = client.bip150.toChallenge();
|
var challenge = client.bip150.toChallenge();
|
||||||
var reply = server.bip150.challenge(challenge);
|
var reply = server.bip150.challenge(challenge.hash);
|
||||||
var propose = client.bip150.reply(reply);
|
var propose = client.bip150.reply(reply);
|
||||||
var challenge = server.bip150.propose(propose);
|
var challenge = server.bip150.propose(propose);
|
||||||
var reply = client.bip150.challenge(challenge);
|
var reply = client.bip150.challenge(challenge);
|
||||||
@ -113,7 +115,7 @@ describe('BIP150', function() {
|
|||||||
|
|
||||||
client.once('rekey', function() {
|
client.once('rekey', function() {
|
||||||
rekeyed = true;
|
rekeyed = true;
|
||||||
var packet = client.packet('encack', client.toRekey());
|
var packet = client.packet('encack', client.toRekey().toRaw());
|
||||||
var emitted = false;
|
var emitted = false;
|
||||||
server.once('packet', function(cmd, body) {
|
server.once('packet', function(cmd, body) {
|
||||||
emitted = true;
|
emitted = true;
|
||||||
|
|||||||
@ -17,15 +17,17 @@ describe('BIP151', function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
it('should do encinit', function() {
|
it('should do encinit', function() {
|
||||||
client.encinit(server.toEncinit());
|
var init = server.toEncinit();
|
||||||
server.encinit(client.toEncinit());
|
client.encinit(init.publicKey, init.cipher);
|
||||||
|
var init = client.toEncinit();
|
||||||
|
server.encinit(init.publicKey, init.cipher);
|
||||||
assert(!client.handshake);
|
assert(!client.handshake);
|
||||||
assert(!server.handshake);
|
assert(!server.handshake);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should do encack', function() {
|
it('should do encack', function() {
|
||||||
client.encack(server.toEncack());
|
client.encack(server.toEncack().publicKey);
|
||||||
server.encack(client.toEncack());
|
server.encack(client.toEncack().publicKey);
|
||||||
assert(client.handshake);
|
assert(client.handshake);
|
||||||
assert(server.handshake);
|
assert(server.handshake);
|
||||||
});
|
});
|
||||||
@ -91,7 +93,7 @@ describe('BIP151', function() {
|
|||||||
|
|
||||||
client.once('rekey', function() {
|
client.once('rekey', function() {
|
||||||
rekeyed = true;
|
rekeyed = true;
|
||||||
var packet = client.packet('encack', client.toRekey());
|
var packet = client.packet('encack', client.toRekey().toRaw());
|
||||||
var emitted = false;
|
var emitted = false;
|
||||||
server.once('packet', function(cmd, body) {
|
server.once('packet', function(cmd, body) {
|
||||||
emitted = true;
|
emitted = true;
|
||||||
|
|||||||
@ -8,9 +8,10 @@ var utils = bcoin.utils;
|
|||||||
var crypto = require('../lib/crypto/crypto');
|
var crypto = require('../lib/crypto/crypto');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var alertData = fs.readFileSync(__dirname + '/data/alertTests.raw');
|
var alertData = fs.readFileSync(__dirname + '/data/alertTests.raw');
|
||||||
var NetworkAddress = bcoin.packets.NetworkAddress;
|
var NetworkAddress = require('../lib/primitives/netaddress');
|
||||||
var Framer = require('../lib/net/framer');
|
var Framer = require('../lib/net/framer');
|
||||||
var Parser = require('../lib/net/parser');
|
var Parser = require('../lib/net/parser');
|
||||||
|
var packets = require('../lib/net/packets');
|
||||||
|
|
||||||
describe('Protocol', function() {
|
describe('Protocol', function() {
|
||||||
var version = require('../package.json').version;
|
var version = require('../package.json').version;
|
||||||
@ -25,17 +26,17 @@ describe('Protocol', function() {
|
|||||||
|
|
||||||
function packetTest(command, payload, test) {
|
function packetTest(command, payload, test) {
|
||||||
it('should encode/decode ' + command, function(cb) {
|
it('should encode/decode ' + command, function(cb) {
|
||||||
var ver = new Buffer(framer[command](payload));
|
var ver = new Buffer(framer.packet(command, payload.toRaw()));
|
||||||
parser.once('packet', function(packet) {
|
parser.once('packet', function(packet) {
|
||||||
assert.equal(packet.cmd, command);
|
assert.equal(packet.cmd, command);
|
||||||
test(packet.payload);
|
test(packet);
|
||||||
cb();
|
cb();
|
||||||
});
|
});
|
||||||
parser.feed(ver);
|
parser.feed(ver);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var v1 = bcoin.packets.VersionPacket.fromOptions({
|
var v1 = packets.VersionPacket.fromOptions({
|
||||||
version: constants.VERSION,
|
version: constants.VERSION,
|
||||||
services: constants.LOCAL_SERVICES,
|
services: constants.LOCAL_SERVICES,
|
||||||
ts: bcoin.now(),
|
ts: bcoin.now(),
|
||||||
@ -54,7 +55,7 @@ describe('Protocol', function() {
|
|||||||
assert.equal(payload.relay, false);
|
assert.equal(payload.relay, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
var v2 = bcoin.packets.VersionPacket.fromOptions({
|
var v2 = packets.VersionPacket.fromOptions({
|
||||||
version: constants.VERSION,
|
version: constants.VERSION,
|
||||||
services: constants.LOCAL_SERVICES,
|
services: constants.LOCAL_SERVICES,
|
||||||
ts: bcoin.now(),
|
ts: bcoin.now(),
|
||||||
@ -73,7 +74,7 @@ describe('Protocol', function() {
|
|||||||
assert.equal(payload.relay, true);
|
assert.equal(payload.relay, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
packetTest('verack', {}, function(payload) {
|
packetTest('verack', new packets.VerackPacket(), function(payload) {
|
||||||
});
|
});
|
||||||
|
|
||||||
var hosts = [
|
var hosts = [
|
||||||
@ -91,19 +92,19 @@ describe('Protocol', function() {
|
|||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
packetTest('addr', hosts, function(payload) {
|
packetTest('addr', new packets.AddrPacket(hosts), function(payload) {
|
||||||
assert.equal(typeof payload.length, 'number');
|
assert.equal(typeof payload.items.length, 'number');
|
||||||
assert.equal(payload.length, 2);
|
assert.equal(payload.items.length, 2);
|
||||||
|
|
||||||
assert.equal(typeof payload[0].ts, 'number');
|
assert.equal(typeof payload.items[0].ts, 'number');
|
||||||
assert.equal(payload[0].services, constants.LOCAL_SERVICES);
|
assert.equal(payload.items[0].services, constants.LOCAL_SERVICES);
|
||||||
assert.equal(payload[0].host, hosts[0].host);
|
assert.equal(payload.items[0].host, hosts[0].host);
|
||||||
assert.equal(payload[0].port, hosts[0].port);
|
assert.equal(payload.items[0].port, hosts[0].port);
|
||||||
|
|
||||||
assert.equal(typeof payload[1].ts, 'number');
|
assert.equal(typeof payload.items[1].ts, 'number');
|
||||||
assert.equal(payload[1].services, constants.LOCAL_SERVICES);
|
assert.equal(payload.items[1].services, constants.LOCAL_SERVICES);
|
||||||
assert.equal(payload[1].host, hosts[1].host);
|
assert.equal(payload.items[1].host, hosts[1].host);
|
||||||
assert.equal(payload[1].port, hosts[1].port);
|
assert.equal(payload.items[1].port, hosts[1].port);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should include the raw data of only one transaction in a ' +
|
it('should include the raw data of only one transaction in a ' +
|
||||||
@ -209,12 +210,12 @@ describe('Protocol', function() {
|
|||||||
var p = new bcoin.reader(alertData);
|
var p = new bcoin.reader(alertData);
|
||||||
p.start();
|
p.start();
|
||||||
while (p.left()) {
|
while (p.left()) {
|
||||||
var alert = bcoin.packets.AlertPacket.fromRaw(p);
|
var alert = packets.AlertPacket.fromRaw(p);
|
||||||
assert(alert.verify(network.alertKey));
|
assert(alert.verify(network.alertKey));
|
||||||
alert._payload = null;
|
alert._payload = null;
|
||||||
alert._hash = null;
|
alert._hash = null;
|
||||||
var data = alert.toRaw();
|
var data = alert.toRaw();
|
||||||
alert = bcoin.packets.AlertPacket.fromRaw(data);
|
alert = packets.AlertPacket.fromRaw(data);
|
||||||
assert(alert.verify(network.alertKey));
|
assert(alert.verify(network.alertKey));
|
||||||
}
|
}
|
||||||
p.end();
|
p.end();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user