packets
This commit is contained in:
parent
9b097f97b9
commit
5da0aceb38
@ -13,7 +13,7 @@ var scrypt = require('./scrypt');
|
||||
var scryptAsync = require('./scrypt-async');
|
||||
var utils = require('../utils/utils');
|
||||
var native = require('../utils/native');
|
||||
var nativeCrypto, supersha, hash, aes;
|
||||
var nativeCrypto, hash, aes;
|
||||
|
||||
var isBrowser =
|
||||
(typeof process !== 'undefined' && process.browser)
|
||||
|
||||
@ -123,6 +123,7 @@ function Environment() {
|
||||
this.require('reader', './utils/reader');
|
||||
this.require('writer', './utils/writer');
|
||||
this.require('lru', './utils/lru');
|
||||
this.require('bloom', './utils/bloom');
|
||||
this.require('uri', './utils/uri');
|
||||
this.require('errors', './utils/errors');
|
||||
|
||||
@ -147,7 +148,6 @@ function Environment() {
|
||||
this.require('sc', './script/sigcache');
|
||||
|
||||
// Primitives
|
||||
this.require('bloom', './primitives/bloom');
|
||||
this.require('address', './primitives/address');
|
||||
this.require('outpoint', './primitives/outpoint');
|
||||
this.require('input', './primitives/input');
|
||||
@ -162,6 +162,7 @@ function Environment() {
|
||||
this.require('merkleblock', './primitives/merkleblock');
|
||||
this.require('headers', './primitives/headers');
|
||||
this.require('keyring', './primitives/keyring');
|
||||
this.require('netaddress', './primitives/netaddress');
|
||||
|
||||
// HD
|
||||
this.require('hd', './hd/hd');
|
||||
|
||||
@ -11,7 +11,7 @@ var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var NetworkAddress = bcoin.packets.NetworkAddress;
|
||||
var NetworkAddress = require('../primitives/netaddress');
|
||||
var fs;
|
||||
|
||||
try {
|
||||
|
||||
@ -12,12 +12,10 @@ var EventEmitter = require('events').EventEmitter;
|
||||
var bcoin = require('../env');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var packets = require('./packets');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
|
||||
var ZERO_SIG = new Buffer(64);
|
||||
ZERO_SIG.fill(0);
|
||||
|
||||
/**
|
||||
* Represents a BIP150 input and output stream.
|
||||
* @exports BIP150
|
||||
@ -76,9 +74,7 @@ BIP150.prototype.isAuthed = function isAuthed() {
|
||||
return this.challengeReceived && this.replyReceived;
|
||||
};
|
||||
|
||||
BIP150.prototype.challenge = function challenge(payload) {
|
||||
var p = bcoin.reader(payload);
|
||||
var hash = p.readHash();
|
||||
BIP150.prototype.challenge = function challenge(hash) {
|
||||
var type = this.outbound ? 'r' : 'i';
|
||||
var msg, sig;
|
||||
|
||||
@ -92,7 +88,7 @@ BIP150.prototype.challenge = function challenge(payload) {
|
||||
msg = this.hash(this.input.sid, type, this.publicKey);
|
||||
|
||||
if (!crypto.ccmp(hash, msg))
|
||||
return ZERO_SIG;
|
||||
return constants.ZERO_SIG64;
|
||||
|
||||
if (this.isAuthed()) {
|
||||
this.auth = true;
|
||||
@ -105,9 +101,7 @@ BIP150.prototype.challenge = function challenge(payload) {
|
||||
return bcoin.ec.fromDER(sig);
|
||||
};
|
||||
|
||||
BIP150.prototype.reply = function reply(payload) {
|
||||
var p = bcoin.reader(payload);
|
||||
var data = p.readBytes(64);
|
||||
BIP150.prototype.reply = function reply(data) {
|
||||
var type = this.outbound ? 'i' : 'r';
|
||||
var sig, msg, result;
|
||||
|
||||
@ -115,7 +109,7 @@ BIP150.prototype.reply = function reply(payload) {
|
||||
assert(!this.replyReceived, 'Peer replied twice.');
|
||||
this.replyReceived = true;
|
||||
|
||||
if (utils.equal(data, ZERO_SIG))
|
||||
if (utils.equal(data, constants.ZERO_SIG64))
|
||||
throw new Error('Auth failure.');
|
||||
|
||||
if (!this.peerIdentity)
|
||||
@ -141,9 +135,7 @@ BIP150.prototype.reply = function reply(payload) {
|
||||
return this.hash(this.input.sid, 'p', this.publicKey);
|
||||
};
|
||||
|
||||
BIP150.prototype.propose = function propose(payload) {
|
||||
var p = bcoin.reader(payload);
|
||||
var hash = p.readHash();
|
||||
BIP150.prototype.propose = function propose(hash) {
|
||||
var match;
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
BIP150.prototype.toChallenge = function toChallenge(writer) {
|
||||
var p = new bcoin.writer(writer);
|
||||
BIP150.prototype.toChallenge = function toChallenge() {
|
||||
var msg;
|
||||
|
||||
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.');
|
||||
this.challengeSent = true;
|
||||
|
||||
p.writeBytes(msg);
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
return p;
|
||||
return new packets.AuthChallengePacket(msg);
|
||||
};
|
||||
|
||||
BIP150.prototype.rekey = function rekey(sid, key, req, res) {
|
||||
|
||||
@ -19,6 +19,7 @@ var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var chachapoly = require('../crypto/chachapoly');
|
||||
var packets = require('./packets');
|
||||
|
||||
/*
|
||||
* Constants
|
||||
@ -526,19 +527,10 @@ BIP151.prototype.isReady = function isReady() {
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
BIP151.prototype.toEncinit = function toEncinit(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
|
||||
p.writeBytes(this.input.getPublicKey());
|
||||
p.writeU8(this.input.cipher);
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
BIP151.prototype.toEncinit = function toEncinit() {
|
||||
assert(!this.initSent, 'Cannot init twice.');
|
||||
this.initSent = true;
|
||||
|
||||
return p;
|
||||
return new packets.EncinitPacket(this.input.getPublicKey(), this.input.cipher);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -547,16 +539,8 @@ BIP151.prototype.toEncinit = function toEncinit(writer) {
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
BIP151.prototype.toEncack = function toEncack(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
|
||||
BIP151.prototype.toEncack = function toEncack() {
|
||||
assert(this.output.prk, 'Cannot ack before init.');
|
||||
|
||||
p.writeBytes(this.output.getPublicKey());
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
assert(!this.ackSent, 'Cannot ack twice.');
|
||||
this.ackSent = true;
|
||||
|
||||
@ -565,7 +549,7 @@ BIP151.prototype.toEncack = function toEncack(writer) {
|
||||
this.emit('handshake');
|
||||
}
|
||||
|
||||
return p;
|
||||
return new packets.EncackPacket(this.output.getPublicKey());
|
||||
};
|
||||
|
||||
/**
|
||||
@ -575,17 +559,9 @@ BIP151.prototype.toEncack = function toEncack(writer) {
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
BIP151.prototype.toRekey = function toRekey(writer) {
|
||||
var p = bcoin.writer(writer);
|
||||
|
||||
BIP151.prototype.toRekey = function toRekey() {
|
||||
assert(this.handshake, 'Cannot rekey before handshake.');
|
||||
|
||||
p.writeBytes(constants.ZERO_KEY);
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
|
||||
return p;
|
||||
return new packets.EncackPacket(constants.ZERO_KEY);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -593,16 +569,10 @@ BIP151.prototype.toRekey = function toRekey(writer) {
|
||||
* @param {Buffer}
|
||||
*/
|
||||
|
||||
BIP151.prototype.encinit = function encinit(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var publicKey = p.readBytes(33);
|
||||
var cipher = p.readU8();
|
||||
|
||||
BIP151.prototype.encinit = function encinit(publicKey, cipher) {
|
||||
assert(cipher === this.output.cipher, 'Cipher mismatch.');
|
||||
assert(!this.initReceived, 'Already initialized.');
|
||||
this.initReceived = true;
|
||||
|
||||
assert(cipher === this.output.cipher, 'Cipher mismatch.');
|
||||
|
||||
this.output.init(publicKey);
|
||||
};
|
||||
|
||||
@ -611,10 +581,7 @@ BIP151.prototype.encinit = function encinit(data) {
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
BIP151.prototype.encack = function encack(data) {
|
||||
var p = bcoin.reader(data);
|
||||
var publicKey = p.readBytes(33);
|
||||
|
||||
BIP151.prototype.encack = function encack(publicKey) {
|
||||
assert(this.initSent, 'Unsolicited ACK.');
|
||||
|
||||
if (utils.equal(publicKey, constants.ZERO_KEY)) {
|
||||
|
||||
@ -552,43 +552,6 @@ TXResponse.prototype.toRaw = function toRaw(witness, writer) {
|
||||
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
|
||||
*/
|
||||
@ -596,4 +559,3 @@ SendCompact.prototype.toRaw = function toRaw(writer) {
|
||||
exports.CompactBlock = CompactBlock;
|
||||
exports.TXRequest = TXRequest;
|
||||
exports.TXResponse = TXResponse;
|
||||
exports.SendCompact = SendCompact;
|
||||
|
||||
@ -11,8 +11,6 @@ var bcoin = require('../env');
|
||||
var utils = require('../utils/utils');
|
||||
var crypto = require('../crypto/crypto');
|
||||
var assert = utils.assert;
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var DUMMY = new Buffer(0);
|
||||
|
||||
/**
|
||||
* Protocol packet framer
|
||||
@ -77,436 +75,6 @@ Framer.prototype.packet = function packet(cmd, payload, checksum) {
|
||||
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
|
||||
*/
|
||||
|
||||
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 assert = utils.assert;
|
||||
var constants = require('../protocol/constants');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var packets = require('./packets');
|
||||
|
||||
/**
|
||||
@ -40,7 +39,7 @@ function Parser(options) {
|
||||
this.pending = [];
|
||||
this.total = 0;
|
||||
this.waiting = 24;
|
||||
this.packet = null;
|
||||
this.header = null;
|
||||
|
||||
this._init();
|
||||
}
|
||||
@ -60,13 +59,13 @@ Parser.prototype._init = function _init(str) {
|
||||
return;
|
||||
|
||||
this.bip151.on('packet', function(cmd, body) {
|
||||
var packet = new Packet(cmd, body.length);
|
||||
var payload;
|
||||
try {
|
||||
packet.payload = self.parsePayload(cmd, body);
|
||||
payload = self.parsePayload(cmd, body);
|
||||
} 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
|
||||
*/
|
||||
|
||||
Parser.prototype._error = function _error(str) {
|
||||
Parser.prototype.error = function error(str) {
|
||||
this.emit('error', new Error(str));
|
||||
};
|
||||
|
||||
@ -120,42 +119,37 @@ Parser.prototype.feed = function feed(data) {
|
||||
* @param {Buffer} chunk
|
||||
*/
|
||||
|
||||
Parser.prototype.parse = function parse(chunk) {
|
||||
var checksum;
|
||||
Parser.prototype.parse = function parse(data) {
|
||||
var payload, checksum;
|
||||
|
||||
if (chunk.length > constants.MAX_MESSAGE) {
|
||||
this.waiting = 24;
|
||||
this.packet = null;
|
||||
return this._error('Packet too large: %dmb.', utils.mb(chunk.length));
|
||||
}
|
||||
assert(data.length <= constants.MAX_MESSAGE);
|
||||
|
||||
if (!this.packet) {
|
||||
this.packet = this.parseHeader(chunk);
|
||||
if (!this.header) {
|
||||
this.header = this.parseHeader(data);
|
||||
this.waiting = this.header.size;
|
||||
return;
|
||||
}
|
||||
|
||||
this.packet.payload = chunk;
|
||||
checksum = crypto.checksum(data).readUInt32LE(0, true);
|
||||
|
||||
checksum = crypto.checksum(this.packet.payload).readUInt32LE(0, true);
|
||||
|
||||
if (checksum !== this.packet.checksum) {
|
||||
if (checksum !== this.header.checksum) {
|
||||
this.waiting = 24;
|
||||
this.packet = null;
|
||||
return this._error('Invalid checksum');
|
||||
this.header = null;
|
||||
return this.error('Invalid checksum');
|
||||
}
|
||||
|
||||
try {
|
||||
this.packet.payload = this.parsePayload(this.packet.cmd, this.packet.payload);
|
||||
payload = this.parsePayload(this.header.cmd, data);
|
||||
} catch (e) {
|
||||
this.emit('error', e);
|
||||
this.waiting = 24;
|
||||
this.packet = null;
|
||||
this.header = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.emit('packet', this.packet);
|
||||
this.emit('packet', payload);
|
||||
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) {
|
||||
var i, magic, cmd, chk;
|
||||
var i, magic, cmd, size, checksum;
|
||||
|
||||
magic = h.readUInt32LE(0, true);
|
||||
|
||||
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
|
||||
for (i = 0; h[i + 4] !== 0 && i < 12; i++);
|
||||
|
||||
if (i === 12)
|
||||
return this._error('Not NULL-terminated cmd');
|
||||
return this.error('Not NULL-terminated cmd');
|
||||
|
||||
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;
|
||||
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) {
|
||||
switch (cmd) {
|
||||
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;
|
||||
}
|
||||
return packets.fromRaw(cmd, 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
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
|
||||
function Packet(cmd, size, checksum) {
|
||||
function Header(cmd, size, checksum) {
|
||||
this.cmd = cmd;
|
||||
this.size = size;
|
||||
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 Parser = require('./parser');
|
||||
var Framer = require('./framer');
|
||||
var packets = require('./packets');
|
||||
var packetTypes = packets.types;
|
||||
var NetworkAddress = require('../primitives/netaddress');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
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.
|
||||
@ -225,7 +223,7 @@ Peer.prototype._init = function init() {
|
||||
});
|
||||
this.bip151.on('rekey', function() {
|
||||
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) {
|
||||
assert(!this.bip151.completed);
|
||||
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) {
|
||||
if (err)
|
||||
self.error(err, true);
|
||||
@ -306,7 +304,7 @@ Peer.prototype._onBIP151 = function _onBIP151() {
|
||||
if (this.bip150.outbound) {
|
||||
if (!this.bip150.peerIdentity)
|
||||
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) {
|
||||
@ -348,7 +346,7 @@ Peer.prototype._onHandshake = function _onHandshake() {
|
||||
if (this.pool.address.host !== '0.0.0.0'
|
||||
&& !this.options.selfish
|
||||
&& 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.
|
||||
if (this.options.headers) {
|
||||
if (this.version.version >= 70012)
|
||||
this.write(this.framer.sendHeaders());
|
||||
this.send(new packets.SendHeadersPacket());
|
||||
}
|
||||
|
||||
// Let them know we support segwit (old
|
||||
@ -392,7 +390,7 @@ Peer.prototype._onAck = function _onAck(err) {
|
||||
// of service bits).
|
||||
if (this.options.witness && this.network.oldWitness) {
|
||||
if (this.version.version >= 70012)
|
||||
this.write(this.framer.haveWitness());
|
||||
this.send(new packets.HaveWitnessPacket());
|
||||
}
|
||||
|
||||
// We want compact blocks!
|
||||
@ -402,7 +400,7 @@ Peer.prototype._onAck = function _onAck(err) {
|
||||
}
|
||||
|
||||
// Find some more peers.
|
||||
this.write(this.framer.getAddr());
|
||||
this.write(new packets.GetAddrPacket());
|
||||
|
||||
// Relay our spv filter if we have one.
|
||||
this.updateWatch();
|
||||
@ -564,7 +562,7 @@ Peer.prototype.sendInv = function sendInv(items) {
|
||||
|
||||
for (i = 0; i < items.length; 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) {
|
||||
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.
|
||||
*/
|
||||
|
||||
Peer.prototype.sendVersion = function sendVersion() {
|
||||
var packet = new VersionPacket({
|
||||
var packet = new packets.VersionPacket({
|
||||
version: constants.VERSION,
|
||||
services: this.pool.services,
|
||||
ts: bcoin.now(),
|
||||
@ -613,8 +620,7 @@ Peer.prototype.sendVersion = function sendVersion() {
|
||||
height: this.chain.height,
|
||||
relay: this.options.relay
|
||||
});
|
||||
|
||||
this.write(this.framer.version(packet));
|
||||
this.send(packet);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -626,7 +632,7 @@ Peer.prototype.sendPing = function sendPing() {
|
||||
return;
|
||||
|
||||
if (this.version.version <= 60000) {
|
||||
this.write(this.framer.ping());
|
||||
this.send(new packets.PingPacket());
|
||||
return;
|
||||
}
|
||||
|
||||
@ -638,7 +644,7 @@ Peer.prototype.sendPing = function sendPing() {
|
||||
this.lastPing = utils.ms();
|
||||
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)
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
var cmd = packet.cmd;
|
||||
var payload = packet.payload;
|
||||
|
||||
if (this.bip151
|
||||
&& !this.bip151.completed
|
||||
&& cmd !== 'encinit'
|
||||
&& cmd !== 'encack') {
|
||||
&& packet.type !== packetTypes.ENCINIT
|
||||
&& packet.type !== packetTypes.ENCACK) {
|
||||
this.bip151.complete(new Error('Message before handshake.'));
|
||||
}
|
||||
|
||||
if (this.bip150
|
||||
&& !this.bip150.completed
|
||||
&& cmd !== 'authchallenge'
|
||||
&& cmd !== 'authreply'
|
||||
&& cmd !== 'authpropose') {
|
||||
&& packet.type !== packetTypes.AUTHCHALLENGE
|
||||
&& packet.type !== packetTypes.AUTHREPLY
|
||||
&& packet.type !== packetTypes.AUTHPROPOSE) {
|
||||
this.bip150.complete(new Error('Message before auth.'));
|
||||
}
|
||||
|
||||
if (this.lastBlock && cmd !== 'tx')
|
||||
if (this.lastBlock && packet.type !== packetTypes.TX)
|
||||
this._flushMerkle();
|
||||
|
||||
this.lastRecv = utils.ms();
|
||||
|
||||
switch (cmd) {
|
||||
case 'version':
|
||||
return this._handleVersion(payload);
|
||||
case 'verack':
|
||||
this.fire(cmd);
|
||||
switch (packet.type) {
|
||||
case packetTypes.VERSION:
|
||||
return this._handleVersion(packet);
|
||||
case packetTypes.VERACK:
|
||||
this.fire(packet.cmd);
|
||||
break;
|
||||
case 'ping':
|
||||
return this._handlePing(payload);
|
||||
case 'pong':
|
||||
return this._handlePong(payload);
|
||||
case 'alert':
|
||||
return this._handleAlert(payload);
|
||||
case 'getaddr':
|
||||
case packetTypes.PING:
|
||||
return this._handlePing(packet);
|
||||
case packetTypes.PONG:
|
||||
return this._handlePong(packet);
|
||||
case packetTypes.ALERT:
|
||||
return this._handleAlert(packet);
|
||||
case packetTypes.GETADDR:
|
||||
return this._handleGetAddr();
|
||||
case 'addr':
|
||||
return this._handleAddr(payload);
|
||||
case 'inv':
|
||||
return this._handleInv(payload);
|
||||
case 'getdata':
|
||||
return this._handleGetData(payload);
|
||||
case 'notfound':
|
||||
this.fire(cmd, payload);
|
||||
case packetTypes.ADDR:
|
||||
return this._handleAddr(packet);
|
||||
case packetTypes.INV:
|
||||
return this._handleInv(packet);
|
||||
case packetTypes.GETDATA:
|
||||
return this._handleGetData(packet);
|
||||
case packetTypes.NOTFOUND:
|
||||
this.fire(packet.cmd, packet.items);
|
||||
break;
|
||||
case 'getblocks':
|
||||
return this._handleGetBlocks(payload);
|
||||
case 'getheaders':
|
||||
return this._handleGetHeaders(payload);
|
||||
case 'headers':
|
||||
return this._handleHeaders(payload);
|
||||
case 'sendheaders':
|
||||
case packetTypes.GETBLOCKS:
|
||||
return this._handleGetBlocks(packet);
|
||||
case packetTypes.GETHEADERS:
|
||||
return this._handleGetHeaders(packet);
|
||||
case packetTypes.HEADERS:
|
||||
return this._handleHeaders(packet);
|
||||
case packetTypes.SENDHEADERS:
|
||||
this.preferHeaders = true;
|
||||
this.fire(cmd);
|
||||
this.fire(packet.cmd);
|
||||
break;
|
||||
case 'block':
|
||||
this.fire(cmd, payload);
|
||||
case packetTypes.BLOCK:
|
||||
this.fire(packet.cmd, packet.block);
|
||||
break;
|
||||
case 'tx':
|
||||
case packetTypes.TX:
|
||||
if (this.lastBlock) {
|
||||
if (this.lastBlock.hasTX(payload)) {
|
||||
this.lastBlock.addTX(payload);
|
||||
if (this.lastBlock.hasTX(packet.tx)) {
|
||||
this.lastBlock.addTX(packet.tx);
|
||||
if (--this.waiting === 0)
|
||||
this._flushMerkle();
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.fire(cmd, payload);
|
||||
this.fire(packet.cmd, packet.tx);
|
||||
break;
|
||||
case 'reject':
|
||||
return this._handleReject(payload);
|
||||
case 'mempool':
|
||||
case packetTypes.REJECT:
|
||||
return this._handleReject(packet);
|
||||
case packetTypes.MEMPOOL:
|
||||
return this._handleMempool();
|
||||
case 'filterload':
|
||||
return this._handleFilterLoad(payload);
|
||||
case 'filteradd':
|
||||
return this._handleFilterAdd(payload);
|
||||
case 'filterclear':
|
||||
case packetTypes.FILTERLOAD:
|
||||
return this._handleFilterLoad(packet);
|
||||
case packetTypes.FILTERADD:
|
||||
return this._handleFilterAdd(packet);
|
||||
case packetTypes.FILTERCLEAR:
|
||||
return this._handleFilterClear();
|
||||
case 'merkleblock':
|
||||
payload.verifyPartial();
|
||||
this.lastBlock = payload;
|
||||
this.waiting = payload.matches.length;
|
||||
case packetTypes.MERKLEBLOCK:
|
||||
packet.block.verifyPartial();
|
||||
this.lastBlock = packet.block;
|
||||
this.waiting = packet.block.matches.length;
|
||||
if (this.waiting === 0)
|
||||
this._flushMerkle();
|
||||
break;
|
||||
case 'getutxos':
|
||||
return this._handleGetUTXOs(payload);
|
||||
case 'utxos':
|
||||
return this._handleUTXOs(payload);
|
||||
case 'havewitness':
|
||||
case packetTypes.GETUTXOS:
|
||||
return this._handleGetUTXOs(packet);
|
||||
case packetTypes.UTXOS:
|
||||
return this._handleUTXOs(packet);
|
||||
case packetTypes.HAVEWITNESS:
|
||||
this.haveWitness = true;
|
||||
this.fire(cmd);
|
||||
this.fire(packet.cmd);
|
||||
break;
|
||||
case 'feefilter':
|
||||
return this._handleFeeFilter(payload);
|
||||
case 'sendcmpct':
|
||||
return this._handleSendCmpct(payload);
|
||||
case 'cmpctblock':
|
||||
return this._handleCmpctBlock(payload);
|
||||
case 'getblocktxn':
|
||||
return this._handleGetBlockTxn(payload);
|
||||
case 'blocktxn':
|
||||
return this._handleBlockTxn(payload);
|
||||
case 'encinit':
|
||||
return this._handleEncinit(payload);
|
||||
case 'encack':
|
||||
return this._handleEncack(payload);
|
||||
case 'authchallenge':
|
||||
return this._handleAuthChallenge(payload);
|
||||
case 'authreply':
|
||||
return this._handleAuthReply(payload);
|
||||
case 'authpropose':
|
||||
return this._handleAuthPropose(payload);
|
||||
default:
|
||||
this.logger.warning('Unknown packet: %s.', cmd);
|
||||
case packetTypes.FEEFILTER:
|
||||
return this._handleFeeFilter(packet);
|
||||
case packetTypes.SENDCMPCT:
|
||||
return this._handleSendCmpct(packet);
|
||||
case packetTypes.CMPCTBLOCK:
|
||||
return this._handleCmpctBlock(packet);
|
||||
case packetTypes.GETBLOCKTXN:
|
||||
return this._handleGetBlockTxn(packet);
|
||||
case packetTypes.BLOCKTXN:
|
||||
return this._handleBlockTxn(packet);
|
||||
case packetTypes.ENCINIT:
|
||||
return this._handleEncinit(packet);
|
||||
case packetTypes.ENCACK:
|
||||
return this._handleEncack(packet);
|
||||
case packetTypes.AUTHCHALLENGE:
|
||||
return this._handleAuthChallenge(packet);
|
||||
case packetTypes.AUTHREPLY:
|
||||
return this._handleAuthReply(packet);
|
||||
case packetTypes.AUTHPROPOSE:
|
||||
return this._handleAuthPropose(packet);
|
||||
case packetTypes.UNKNOWN:
|
||||
this.logger.warning('Unknown packet: %s.', packet.cmd);
|
||||
break;
|
||||
}
|
||||
};
|
||||
@ -1008,13 +1011,13 @@ Peer.prototype.fire = function fire(cmd, payload) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleFilterLoad = function _handleFilterLoad(filter) {
|
||||
if (!filter.isWithinConstraints()) {
|
||||
Peer.prototype._handleFilterLoad = function _handleFilterLoad(packet) {
|
||||
if (!packet.isWithinConstraints()) {
|
||||
this.setMisbehavior(100);
|
||||
return;
|
||||
}
|
||||
|
||||
this.spvFilter = filter;
|
||||
this.spvFilter = packet.toFilter();
|
||||
this.relay = true;
|
||||
};
|
||||
|
||||
@ -1024,7 +1027,9 @@ Peer.prototype._handleFilterLoad = function _handleFilterLoad(filter) {
|
||||
* @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) {
|
||||
this.setMisbehavior(100);
|
||||
return;
|
||||
@ -1055,7 +1060,9 @@ Peer.prototype._handleFilterClear = function _handleFilterClear() {
|
||||
* @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)) {
|
||||
this.setMisbehavior(100);
|
||||
return;
|
||||
@ -1111,7 +1118,7 @@ Peer.prototype._handleGetUTXOs = function _handleGetUTXOs(payload) {
|
||||
if (payload.prevout.length > 15)
|
||||
return done();
|
||||
|
||||
utxos = new GetUTXOsPacket();
|
||||
utxos = new packets.GetUTXOsPacket();
|
||||
|
||||
utils.forEachSerial(payload.prevout, function(prevout, next) {
|
||||
var hash = prevout.hash;
|
||||
@ -1154,7 +1161,7 @@ Peer.prototype._handleGetUTXOs = function _handleGetUTXOs(payload) {
|
||||
utxos.height = self.chain.height;
|
||||
utxos.tip = self.chain.tip.hash;
|
||||
|
||||
self.write(self.framer.UTXOs(utxos));
|
||||
self.send(new packets.UTXOsPacket(utxos));
|
||||
|
||||
done();
|
||||
});
|
||||
@ -1378,8 +1385,7 @@ Peer.prototype._handleVersion = function _handleVersion(version) {
|
||||
if (!version.relay)
|
||||
this.relay = false;
|
||||
|
||||
// ACK
|
||||
this.write(this.framer.verack());
|
||||
this.send(new packets.VerackPacket());
|
||||
this.version = version;
|
||||
this.fire('version', version);
|
||||
};
|
||||
@ -1482,10 +1488,11 @@ Peer.prototype._getItem = function _getItem(item, callback) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleGetData = function _handleGetData(items) {
|
||||
Peer.prototype._handleGetData = function _handleGetData(packet) {
|
||||
var self = this;
|
||||
var notFound = [];
|
||||
var unlock = this._lock(_handleGetData, [items, utils.nop]);
|
||||
var items = packet.items;
|
||||
var unlock = this._lock(_handleGetData, [packet, utils.nop]);
|
||||
|
||||
if (!unlock)
|
||||
return;
|
||||
@ -1528,10 +1535,7 @@ Peer.prototype._handleGetData = function _handleGetData(items) {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (item.hasWitness())
|
||||
self.write(self.framer.witnessTX(tx));
|
||||
else
|
||||
self.write(self.framer.tx(tx));
|
||||
self.send(new packets.TXPacket(tx, item.hasWitness()));
|
||||
|
||||
return next();
|
||||
}
|
||||
@ -1541,10 +1545,7 @@ Peer.prototype._handleGetData = function _handleGetData(items) {
|
||||
switch (item.type) {
|
||||
case constants.inv.BLOCK:
|
||||
case constants.inv.WITNESS_BLOCK:
|
||||
if (item.hasWitness())
|
||||
self.write(self.framer.witnessBlock(block));
|
||||
else
|
||||
self.write(self.framer.block(block));
|
||||
self.send(new packets.BlockPacket(block, item.hasWitness()));
|
||||
break;
|
||||
case constants.inv.FILTERED_BLOCK:
|
||||
case constants.inv.WITNESS_FILTERED_BLOCK:
|
||||
@ -1555,22 +1556,18 @@ Peer.prototype._handleGetData = function _handleGetData(items) {
|
||||
|
||||
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++) {
|
||||
tx = block.txs[i];
|
||||
|
||||
if (item.hasWitness())
|
||||
self.write(self.framer.witnessTX(tx));
|
||||
else
|
||||
self.write(self.framer.tx(tx));
|
||||
self.send(new packets.TXPacket(tx, item.hasWitness()));
|
||||
}
|
||||
|
||||
break;
|
||||
case constants.inv.CMPCT_BLOCK:
|
||||
// Fallback to full block.
|
||||
if (block.height < self.chain.tip.height - 10) {
|
||||
self.write(self.framer.block(block));
|
||||
self.send(new packets.BlockPacket(block, false));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1585,7 +1582,7 @@ Peer.prototype._handleGetData = function _handleGetData(items) {
|
||||
break;
|
||||
}
|
||||
|
||||
self.write(self.framer.cmpctBlock(block));
|
||||
self.send(new packets.CmpctBlockPacket(block, false));
|
||||
break;
|
||||
default:
|
||||
self.logger.warning(
|
||||
@ -1614,7 +1611,7 @@ Peer.prototype._handleGetData = function _handleGetData(items) {
|
||||
self.hostname);
|
||||
|
||||
if (notFound.length > 0)
|
||||
self.write(self.framer.notFound(notFound));
|
||||
self.send(new packets.NotFoundPacket(notFound));
|
||||
|
||||
done();
|
||||
});
|
||||
@ -1626,7 +1623,8 @@ Peer.prototype._handleGetData = function _handleGetData(items) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleAddr = function _handleAddr(addrs) {
|
||||
Peer.prototype._handleAddr = function _handleAddr(packet) {
|
||||
var addrs = packet.items;
|
||||
var i;
|
||||
|
||||
for (i = 0; i < addrs.length; i++)
|
||||
@ -1648,8 +1646,8 @@ Peer.prototype._handleAddr = function _handleAddr(addrs) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handlePing = function _handlePing(nonce) {
|
||||
this.write(this.framer.pong(nonce));
|
||||
Peer.prototype._handlePing = function _handlePing(packet) {
|
||||
this.send(new packets.PongPacket(packet.nonce));
|
||||
this.fire('ping', this.minPing);
|
||||
};
|
||||
|
||||
@ -1659,7 +1657,8 @@ Peer.prototype._handlePing = function _handlePing(nonce) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handlePong = function _handlePong(nonce) {
|
||||
Peer.prototype._handlePong = function _handlePong(packet) {
|
||||
var nonce = packet.nonce;
|
||||
var now = utils.ms();
|
||||
|
||||
if (!this.challenge) {
|
||||
@ -1734,7 +1733,7 @@ Peer.prototype._handleGetAddr = function _handleGetAddr() {
|
||||
items.length,
|
||||
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}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleInv = function _handleInv(items) {
|
||||
Peer.prototype._handleInv = function _handleInv(packet) {
|
||||
var items = packet.items;
|
||||
var blocks = [];
|
||||
var txs = [];
|
||||
var i, item, unknown;
|
||||
var unknown = -1;
|
||||
var i, item;
|
||||
|
||||
if (items.length > 50000) {
|
||||
this.setMisbehavior(100);
|
||||
@ -1755,13 +1756,16 @@ Peer.prototype._handleInv = function _handleInv(items) {
|
||||
|
||||
for (i = 0; i < items.length; i++) {
|
||||
item = items[i];
|
||||
if (item.type === constants.inv.TX) {
|
||||
txs.push(item.hash);
|
||||
} else if (item.type === constants.inv.BLOCK) {
|
||||
blocks.push(item.hash);
|
||||
} else {
|
||||
unknown = item.type;
|
||||
continue;
|
||||
switch (item.type) {
|
||||
case constants.inv.TX:
|
||||
txs.push(item.hash);
|
||||
break;
|
||||
case constants.inv.BLOCK:
|
||||
blocks.push(item.hash);
|
||||
break;
|
||||
default:
|
||||
unknown = item.type;
|
||||
continue;
|
||||
}
|
||||
this.invFilter.add(item.hash, 'hex');
|
||||
}
|
||||
@ -1774,7 +1778,7 @@ Peer.prototype._handleInv = function _handleInv(items) {
|
||||
if (txs.length > 0)
|
||||
this.emit('txs', txs);
|
||||
|
||||
if (unknown != null) {
|
||||
if (unknown !== -1) {
|
||||
this.logger.warning(
|
||||
'Peer sent an unknown inv type: %d (%s).',
|
||||
unknown, this.hostname);
|
||||
@ -1787,7 +1791,8 @@ Peer.prototype._handleInv = function _handleInv(items) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleHeaders = function _handleHeaders(headers) {
|
||||
Peer.prototype._handleHeaders = function _handleHeaders(packet) {
|
||||
var headers = packet.items;
|
||||
if (headers.length > 2000) {
|
||||
this.setMisbehavior(100);
|
||||
return;
|
||||
@ -1835,20 +1840,20 @@ Peer.prototype._handleAlert = function _handleAlert(alert) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleEncinit = function _handleEncinit(data) {
|
||||
Peer.prototype._handleEncinit = function _handleEncinit(packet) {
|
||||
if (!this.bip151)
|
||||
return;
|
||||
|
||||
try {
|
||||
this.bip151.encinit(data);
|
||||
this.bip151.encinit(packet.publicKey, packet.cipher);
|
||||
} catch (e) {
|
||||
this.error(e);
|
||||
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}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleEncack = function _handleEncack(data) {
|
||||
Peer.prototype._handleEncack = function _handleEncack(packet) {
|
||||
if (!this.bip151)
|
||||
return;
|
||||
|
||||
try {
|
||||
this.bip151.encack(data);
|
||||
this.bip151.encack(packet.publicKey);
|
||||
} catch (e) {
|
||||
this.error(e);
|
||||
return;
|
||||
}
|
||||
|
||||
this.fire('encack', data);
|
||||
this.fire('encack', packet);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1877,22 +1882,22 @@ Peer.prototype._handleEncack = function _handleEncack(data) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleAuthChallenge = function _handleAuthChallenge(data) {
|
||||
var result;
|
||||
Peer.prototype._handleAuthChallenge = function _handleAuthChallenge(packet) {
|
||||
var sig;
|
||||
|
||||
if (!this.bip150)
|
||||
return;
|
||||
|
||||
try {
|
||||
result = this.bip150.challenge(data);
|
||||
sig = this.bip150.challenge(packet.hash);
|
||||
} catch (e) {
|
||||
this.error(e);
|
||||
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}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleAuthReply = function _handleAuthReply(data) {
|
||||
var result;
|
||||
Peer.prototype._handleAuthReply = function _handleAuthReply(packet) {
|
||||
var hash;
|
||||
|
||||
if (!this.bip150)
|
||||
return;
|
||||
|
||||
try {
|
||||
result = this.bip150.reply(data);
|
||||
hash = this.bip150.reply(packet.signature);
|
||||
} catch (e) {
|
||||
this.error(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result)
|
||||
this.write(this.framer.authPropose(result));
|
||||
if (hash)
|
||||
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}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleAuthPropose = function _handleAuthPropose(data) {
|
||||
var result;
|
||||
Peer.prototype._handleAuthPropose = function _handleAuthPropose(packet) {
|
||||
var hash;
|
||||
|
||||
if (!this.bip150)
|
||||
return;
|
||||
|
||||
try {
|
||||
result = this.bip150.propose(data);
|
||||
hash = this.bip150.propose(packet.hash);
|
||||
} catch (e) {
|
||||
this.error(e);
|
||||
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}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleSendCmpct = function _handleSendCmpct(cmpct) {
|
||||
if (cmpct.version !== 1) {
|
||||
Peer.prototype._handleSendCmpct = function _handleSendCmpct(packet) {
|
||||
if (packet.version !== 1) {
|
||||
// Ignore
|
||||
this.logger.info('Peer request compact blocks version %d (%s).',
|
||||
cmpct.version, this.hostname);
|
||||
packet.version, this.hostname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmpct.mode !== 0) {
|
||||
if (packet.mode !== 0) {
|
||||
// Ignore (we can't do mode 1 yet).
|
||||
this.logger.info('Peer request compact blocks mode %d (%s).',
|
||||
cmpct.mode, this.hostname);
|
||||
packet.mode, this.hostname);
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.info('Peer initialized compact blocks (%s).', this.hostname);
|
||||
|
||||
this.compactMode = cmpct;
|
||||
this.fire('sendcmpct', cmpct);
|
||||
this.compactMode = packet;
|
||||
this.fire('sendcmpct', packet);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1977,8 +1982,9 @@ Peer.prototype._handleSendCmpct = function _handleSendCmpct(cmpct) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleCmpctBlock = function _handleCmpctBlock(block) {
|
||||
Peer.prototype._handleCmpctBlock = function _handleCmpctBlock(packet) {
|
||||
var self = this;
|
||||
var block = packet.block;
|
||||
var hash = block.hash('hex');
|
||||
var result;
|
||||
|
||||
@ -2013,7 +2019,7 @@ Peer.prototype._handleCmpctBlock = function _handleCmpctBlock(block) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.write(this.framer.getBlockTxn(block.toRequest()));
|
||||
this.send(block.toRequest());
|
||||
|
||||
this.logger.debug(
|
||||
'Received semi-full compact block %s (%s).',
|
||||
@ -2033,8 +2039,9 @@ Peer.prototype._handleCmpctBlock = function _handleCmpctBlock(block) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleGetBlockTxn = function _handleGetBlockTxn(req) {
|
||||
Peer.prototype._handleGetBlockTxn = function _handleGetBlockTxn(packet) {
|
||||
var self = this;
|
||||
var req = packet.request;
|
||||
var res, item;
|
||||
|
||||
function done(err) {
|
||||
@ -2077,7 +2084,7 @@ Peer.prototype._handleGetBlockTxn = function _handleGetBlockTxn(req) {
|
||||
|
||||
res = bcoin.bip152.TXResponse.fromBlock(block, req);
|
||||
|
||||
self.write(self.framer.blockTxn(res));
|
||||
self.send(new packets.BlockTxnPacket(res, false));
|
||||
|
||||
done();
|
||||
});
|
||||
@ -2089,7 +2096,8 @@ Peer.prototype._handleGetBlockTxn = function _handleGetBlockTxn(req) {
|
||||
* @param {Object}
|
||||
*/
|
||||
|
||||
Peer.prototype._handleBlockTxn = function _handleBlockTxn(res) {
|
||||
Peer.prototype._handleBlockTxn = function _handleBlockTxn(packet) {
|
||||
var res = packet.response;
|
||||
var block = this.compactBlocks[res.hash];
|
||||
|
||||
if (!block) {
|
||||
@ -2124,7 +2132,7 @@ Peer.prototype.sendAlert = function sendAlert(alert) {
|
||||
if (!this.invFilter.added(alert.hash()))
|
||||
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) {
|
||||
var packet = new GetBlocksPacket(locator, stop);
|
||||
var packet = new packets.GetHeadersPacket(locator, stop);
|
||||
var height = -1;
|
||||
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.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) {
|
||||
var packet = new GetBlocksPacket(locator, stop);
|
||||
var packet = new packets.GetBlocksPacket(locator, stop);
|
||||
var height = -1;
|
||||
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.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).',
|
||||
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) {
|
||||
var reject = RejectPacket.fromReason(code, reason, obj);
|
||||
var reject = packets.RejectPacket.fromReason(code, reason, obj);
|
||||
|
||||
if (obj) {
|
||||
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).',
|
||||
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() {
|
||||
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.write(this.framer.sendCmpct(cmpct));
|
||||
this.send(cmpct);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -15,7 +15,7 @@ var IP = require('../utils/ip');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.constants;
|
||||
var VerifyError = bcoin.errors.VerifyError;
|
||||
var NetworkAddress = bcoin.packets.NetworkAddress;
|
||||
var NetworkAddress = require('../primitives/netaddress');
|
||||
var InvItem = bcoin.invitem;
|
||||
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'
|
||||
);
|
||||
|
||||
/**
|
||||
* A hash of all 0xff.
|
||||
* @const {String}
|
||||
* @default
|
||||
*/
|
||||
|
||||
exports.MAX_HASH160 = new Buffer(
|
||||
'ffffffffffffffffffffffffffffffffffffffff',
|
||||
'hex'
|
||||
);
|
||||
|
||||
/**
|
||||
* A hash of all zeroes.
|
||||
* @const {String}
|
||||
@ -639,6 +650,14 @@ exports.ZERO_HASH160 = new Buffer(
|
||||
|
||||
exports.NULL_HASH160 = '0000000000000000000000000000000000000000';
|
||||
|
||||
/**
|
||||
* A hash of all 0xff.
|
||||
* @const {String}
|
||||
* @default
|
||||
*/
|
||||
|
||||
exports.HIGH_HASH160 = 'ffffffffffffffffffffffffffffffffffffffff';
|
||||
|
||||
/**
|
||||
* A compressed pubkey of all zeroes.
|
||||
* @const {Buffer}
|
||||
@ -650,6 +669,31 @@ exports.ZERO_KEY = new Buffer(
|
||||
'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.
|
||||
* @const {String}
|
||||
|
||||
@ -8,10 +8,7 @@
|
||||
'use strict';
|
||||
|
||||
var constants = require('../protocol/constants');
|
||||
var assert = require('assert');
|
||||
var BufferReader = require('../utils/reader');
|
||||
var BufferWriter = require('../utils/writer');
|
||||
var murmur3 = require('../utils/murmur3');
|
||||
var murmur3 = require('./murmur3');
|
||||
var sum32 = murmur3.sum32;
|
||||
var mul32 = murmur3.mul32;
|
||||
|
||||
@ -147,66 +144,6 @@ Bloom.prototype.added = function added(val, enc) {
|
||||
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.
|
||||
* @param {Number} items - Expeected number of items.
|
||||
@ -415,11 +352,15 @@ RollingFilter.prototype.added = function added(val, enc) {
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function U64(hi, lo) {
|
||||
this.hi = hi;
|
||||
this.lo = lo;
|
||||
}
|
||||
|
||||
function read(data, off) {
|
||||
return {
|
||||
hi: data.readUInt32LE(off + 4, true),
|
||||
lo: data.readUInt32LE(off, true)
|
||||
};
|
||||
var hi = data.readUInt32LE(off + 4, true);
|
||||
var lo = data.readUInt32LE(off, true);
|
||||
return new U64(hi, lo);
|
||||
}
|
||||
|
||||
function write(data, value, off) {
|
||||
@ -27,15 +27,17 @@ describe('BIP150', function() {
|
||||
}
|
||||
|
||||
it('should do encinit', function() {
|
||||
client.encinit(server.toEncinit());
|
||||
server.encinit(client.toEncinit());
|
||||
var init = server.toEncinit();
|
||||
client.encinit(init.publicKey, init.cipher);
|
||||
var init = client.toEncinit();
|
||||
server.encinit(init.publicKey, init.cipher);
|
||||
assert(!client.handshake);
|
||||
assert(!server.handshake);
|
||||
});
|
||||
|
||||
it('should do encack', function() {
|
||||
client.encack(server.toEncack());
|
||||
server.encack(client.toEncack());
|
||||
client.encack(server.toEncack().publicKey);
|
||||
server.encack(client.toEncack().publicKey);
|
||||
assert(client.handshake);
|
||||
assert(server.handshake);
|
||||
});
|
||||
@ -49,7 +51,7 @@ describe('BIP150', function() {
|
||||
|
||||
it('should do BIP150 handshake', function() {
|
||||
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 challenge = server.bip150.propose(propose);
|
||||
var reply = client.bip150.challenge(challenge);
|
||||
@ -113,7 +115,7 @@ describe('BIP150', function() {
|
||||
|
||||
client.once('rekey', function() {
|
||||
rekeyed = true;
|
||||
var packet = client.packet('encack', client.toRekey());
|
||||
var packet = client.packet('encack', client.toRekey().toRaw());
|
||||
var emitted = false;
|
||||
server.once('packet', function(cmd, body) {
|
||||
emitted = true;
|
||||
|
||||
@ -17,15 +17,17 @@ describe('BIP151', function() {
|
||||
}
|
||||
|
||||
it('should do encinit', function() {
|
||||
client.encinit(server.toEncinit());
|
||||
server.encinit(client.toEncinit());
|
||||
var init = server.toEncinit();
|
||||
client.encinit(init.publicKey, init.cipher);
|
||||
var init = client.toEncinit();
|
||||
server.encinit(init.publicKey, init.cipher);
|
||||
assert(!client.handshake);
|
||||
assert(!server.handshake);
|
||||
});
|
||||
|
||||
it('should do encack', function() {
|
||||
client.encack(server.toEncack());
|
||||
server.encack(client.toEncack());
|
||||
client.encack(server.toEncack().publicKey);
|
||||
server.encack(client.toEncack().publicKey);
|
||||
assert(client.handshake);
|
||||
assert(server.handshake);
|
||||
});
|
||||
@ -91,7 +93,7 @@ describe('BIP151', function() {
|
||||
|
||||
client.once('rekey', function() {
|
||||
rekeyed = true;
|
||||
var packet = client.packet('encack', client.toRekey());
|
||||
var packet = client.packet('encack', client.toRekey().toRaw());
|
||||
var emitted = false;
|
||||
server.once('packet', function(cmd, body) {
|
||||
emitted = true;
|
||||
|
||||
@ -8,9 +8,10 @@ var utils = bcoin.utils;
|
||||
var crypto = require('../lib/crypto/crypto');
|
||||
var fs = require('fs');
|
||||
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 Parser = require('../lib/net/parser');
|
||||
var packets = require('../lib/net/packets');
|
||||
|
||||
describe('Protocol', function() {
|
||||
var version = require('../package.json').version;
|
||||
@ -25,17 +26,17 @@ describe('Protocol', function() {
|
||||
|
||||
function packetTest(command, payload, test) {
|
||||
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) {
|
||||
assert.equal(packet.cmd, command);
|
||||
test(packet.payload);
|
||||
test(packet);
|
||||
cb();
|
||||
});
|
||||
parser.feed(ver);
|
||||
});
|
||||
}
|
||||
|
||||
var v1 = bcoin.packets.VersionPacket.fromOptions({
|
||||
var v1 = packets.VersionPacket.fromOptions({
|
||||
version: constants.VERSION,
|
||||
services: constants.LOCAL_SERVICES,
|
||||
ts: bcoin.now(),
|
||||
@ -54,7 +55,7 @@ describe('Protocol', function() {
|
||||
assert.equal(payload.relay, false);
|
||||
});
|
||||
|
||||
var v2 = bcoin.packets.VersionPacket.fromOptions({
|
||||
var v2 = packets.VersionPacket.fromOptions({
|
||||
version: constants.VERSION,
|
||||
services: constants.LOCAL_SERVICES,
|
||||
ts: bcoin.now(),
|
||||
@ -73,7 +74,7 @@ describe('Protocol', function() {
|
||||
assert.equal(payload.relay, true);
|
||||
});
|
||||
|
||||
packetTest('verack', {}, function(payload) {
|
||||
packetTest('verack', new packets.VerackPacket(), function(payload) {
|
||||
});
|
||||
|
||||
var hosts = [
|
||||
@ -91,19 +92,19 @@ describe('Protocol', function() {
|
||||
})
|
||||
];
|
||||
|
||||
packetTest('addr', hosts, function(payload) {
|
||||
assert.equal(typeof payload.length, 'number');
|
||||
assert.equal(payload.length, 2);
|
||||
packetTest('addr', new packets.AddrPacket(hosts), function(payload) {
|
||||
assert.equal(typeof payload.items.length, 'number');
|
||||
assert.equal(payload.items.length, 2);
|
||||
|
||||
assert.equal(typeof payload[0].ts, 'number');
|
||||
assert.equal(payload[0].services, constants.LOCAL_SERVICES);
|
||||
assert.equal(payload[0].host, hosts[0].host);
|
||||
assert.equal(payload[0].port, hosts[0].port);
|
||||
assert.equal(typeof payload.items[0].ts, 'number');
|
||||
assert.equal(payload.items[0].services, constants.LOCAL_SERVICES);
|
||||
assert.equal(payload.items[0].host, hosts[0].host);
|
||||
assert.equal(payload.items[0].port, hosts[0].port);
|
||||
|
||||
assert.equal(typeof payload[1].ts, 'number');
|
||||
assert.equal(payload[1].services, constants.LOCAL_SERVICES);
|
||||
assert.equal(payload[1].host, hosts[1].host);
|
||||
assert.equal(payload[1].port, hosts[1].port);
|
||||
assert.equal(typeof payload.items[1].ts, 'number');
|
||||
assert.equal(payload.items[1].services, constants.LOCAL_SERVICES);
|
||||
assert.equal(payload.items[1].host, hosts[1].host);
|
||||
assert.equal(payload.items[1].port, hosts[1].port);
|
||||
});
|
||||
|
||||
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);
|
||||
p.start();
|
||||
while (p.left()) {
|
||||
var alert = bcoin.packets.AlertPacket.fromRaw(p);
|
||||
var alert = packets.AlertPacket.fromRaw(p);
|
||||
assert(alert.verify(network.alertKey));
|
||||
alert._payload = null;
|
||||
alert._hash = null;
|
||||
var data = alert.toRaw();
|
||||
alert = bcoin.packets.AlertPacket.fromRaw(data);
|
||||
alert = packets.AlertPacket.fromRaw(data);
|
||||
assert(alert.verify(network.alertKey));
|
||||
}
|
||||
p.end();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user