fcoin/lib/net/packets.js
2016-10-02 23:24:11 -07:00

3053 lines
63 KiB
JavaScript

/*!
* 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 bn = require('bn.js');
var constants = require('../protocol/constants');
var utils = require('../utils/utils');
var assert = require('assert');
var crypto = require('../crypto/crypto');
var time = require('./timedata');
var ec = require('../crypto/ec');
var Bloom = require('../utils/bloom');
var bip152 = require('./bip152');
var NetworkAddress = require('../primitives/netaddress');
var Coin = require('../primitives/coin');
var Headers = require('../primitives/headers');
var InvItem = require('../primitives/invitem');
var MemBlock = require('../primitives/memblock');
var MerkleBlock = require('../primitives/merkleblock');
var Outpoint = require('../primitives/outpoint');
var Output = require('../primitives/output');
var TX = require('../primitives/tx');
var BufferWriter = require('../utils/writer');
var BufferReader = require('../utils/reader');
var DUMMY = new Buffer(0);
/**
* Packet types.
* @enum {Number}
* @default
*/
exports.types = {
VERSION: 0,
VERACK: 1,
PING: 1,
PONG: 2,
ALERT: 3,
GETADDR: 4,
ADDR: 5,
INV: 6,
GETDATA: 7,
NOTFOUND: 8,
GETBLOCKS: 9,
GETHEADERS: 10,
HEADERS: 11,
SENDHEADERS: 12,
BLOCK: 13,
TX: 14,
REJECT: 15,
MEMPOOL: 16,
FILTERLOAD: 17,
FILTERADD: 18,
FILTERCLEAR: 19,
MERKLEBLOCK: 20,
GETUTXOS: 21,
UTXOS: 22,
HAVEWITNESS: 23,
FEEFILTER: 24,
SENDCMPCT: 25,
CMPCTBLOCK: 26,
GETBLOCKTXN: 27,
BLOCKTXN: 28,
ENCINIT: 29,
ENCACK: 30,
AUTHCHALLENGE: 31,
AUTHREPLY: 32,
AUTHPROPOSE: 33,
UNKNOWN: 34
};
/**
* Base Packet
* @constructor
*/
function Packet() {}
Packet.prototype.type = -1;
Packet.prototype.cmd = '';
/**
* Version Packet
* @constructor
* @exports VersionPacket
* @param {Object?} options
* @param {Number} options.version - Protocol version.
* @param {Number} options.services - Service bits.
* @param {Number} options.ts - Timestamp of discovery.
* @param {NetworkAddress} options.local - Our address.
* @param {NetworkAddress} options.remote - Their address.
* @param {BN} options.nonce
* @param {String} options.agent - User agent string.
* @param {Number} options.height - Chain height.
* @param {Boolean} options.relay - Whether transactions
* should be relayed immediately.
* @property {Number} version - Protocol version.
* @property {Number} services - Service bits.
* @property {Number} ts - Timestamp of discovery.
* @property {NetworkAddress} local - Our address.
* @property {NetworkAddress} remote - Their address.
* @property {BN} nonce
* @property {String} agent - User agent string.
* @property {Number} height - Chain height.
* @property {Boolean} relay - Whether transactions
* should be relayed immediately.
*/
function VersionPacket(options) {
if (!(this instanceof VersionPacket))
return new VersionPacket(options);
Packet.call(this);
this.version = constants.VERSION;
this.services = constants.LOCAL_SERVICES;
this.ts = time.now();
this.recv = new NetworkAddress();
this.from = new NetworkAddress();
this.nonce = new bn(0);
this.agent = constants.USER_AGENT;
this.height = 0;
this.relay = true;
if (options)
this.fromOptions(options);
}
utils.inherits(VersionPacket, Packet);
VersionPacket.prototype.cmd = 'version';
VersionPacket.prototype.type = exports.types.VERSION;
/**
* Inject properties from options.
* @private
* @param {Object} options
*/
VersionPacket.prototype.fromOptions = function fromOptions(options) {
if (options.version != null)
this.version = options.version;
if (options.services != null)
this.services = options.services;
if (options.ts != null)
this.ts = options.ts;
if (options.recv)
this.recv.fromOptions(options.recv);
if (options.from)
this.from.fromOptions(options.from);
if (options.nonce)
this.nonce = options.nonce;
if (options.agent)
this.agent = options.agent;
if (options.height != null)
this.height = options.height;
if (options.relay != null)
this.relay = options.relay;
return this;
};
/**
* Instantiate version packet from options.
* @param {Object} options
* @returns {VersionPacket}
*/
VersionPacket.fromOptions = function fromOptions(options) {
return new VersionPacket().fromOptions(options);
};
/**
* Serialize version packet.
* @returns {Buffer}
*/
VersionPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
p.write32(this.version);
p.writeU64(this.services);
p.write64(this.ts);
this.recv.toRaw(false, p);
this.from.toRaw(false, p);
p.writeU64(this.nonce);
p.writeVarString(this.agent, 'ascii');
p.write32(this.height);
p.writeU8(this.relay ? 1 : 0);
if (!writer)
p = p.render();
return p;
};
/**
* Test whether the NETWORK service bit is set.
* @returns {Boolean}
*/
VersionPacket.prototype.hasNetwork = function hasNetwork() {
return (this.services & constants.services.NETWORK) !== 0;
};
/**
* Test whether the BLOOM service bit is set.
* @returns {Boolean}
*/
VersionPacket.prototype.hasBloom = function hasBloom() {
return this.version >= 70011
&& (this.services & constants.services.BLOOM) !== 0;
};
/**
* Test whether the GETUTXO service bit is set.
* @returns {Boolean}
*/
VersionPacket.prototype.hasUTXO = function hasUTXO() {
return (this.services & constants.services.GETUTXO) !== 0;
};
/**
* Test whether the WITNESS service bit is set.
* @returns {Boolean}
*/
VersionPacket.prototype.hasWitness = function hasWitness() {
return (this.services & constants.services.WITNESS) !== 0;
};
/**
* Test whether the protocol version supports getheaders.
* @returns {Boolean}
*/
VersionPacket.prototype.hasHeaders = function hasHeaders() {
return this.version >= 31800;
};
/**
* Test whether the protocol version supports bip152.
* @returns {Boolean}
*/
VersionPacket.prototype.hasCompact = function hasCompact() {
return this.version >= 70014;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
VersionPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
this.version = p.read32();
this.services = p.readU53();
this.ts = p.read53();
this.recv.fromRaw(p, false);
if (p.left() > 0) {
this.from.fromRaw(p, false);
this.nonce = p.readU64();
}
if (p.left() > 0)
this.agent = p.readVarString('ascii', 256);
if (p.left() > 0)
this.height = p.read32();
if (p.left() > 0)
this.relay = p.readU8() === 1;
if (this.version === 10300)
this.version = 300;
assert(this.version >= 0, 'Version is negative.');
assert(this.ts >= 0, 'Timestamp is negative.');
// assert(this.height >= 0, 'Height is negative.');
return this;
};
/**
* Instantiate version packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {VersionPacket}
*/
VersionPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new VersionPacket().fromRaw(data, enc);
};
/**
* Represents a `verack` packet.
* @exports VerackPacket
* @constructor
*/
function VerackPacket() {
if (!(this instanceof VerackPacket))
return new VerackPacket();
Packet.call(this);
}
VerackPacket.prototype.cmd = 'verack';
VerackPacket.prototype.type = exports.types.VERACK;
/**
* Serialize verack packet.
* @returns {Buffer}
*/
VerackPacket.prototype.toRaw = function toRaw(writer) {
return writer || DUMMY;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
VerackPacket.prototype.fromRaw = function fromRaw(data) {
return this;
};
/**
* Instantiate verack packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {VerackPacket}
*/
VerackPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new VerackPacket().fromRaw(data);
};
/**
* Represents a `ping` packet.
* @exports PingPacket
* @constructor
* @param {BN?} nonce
* @property {BN|null} nonce
*/
function PingPacket(nonce) {
if (!(this instanceof PingPacket))
return new PingPacket(nonce);
Packet.call(this);
this.nonce = nonce || null;
}
utils.inherits(PingPacket, Packet);
PingPacket.prototype.cmd = 'ping';
PingPacket.prototype.type = exports.types.PING;
/**
* Serialize ping packet.
* @returns {Buffer}
*/
PingPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
if (this.nonce)
p.writeU64(this.nonce);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
PingPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
if (p.left() >= 8)
this.nonce = p.readU64();
return this;
};
/**
* Instantiate ping packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {PingPacket}
*/
PingPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new PingPacket().fromRaw(data);
};
/**
* Represents a `pong` packet.
* @exports PongPacket
* @constructor
* @param {BN?} nonce
* @property {BN} nonce
*/
function PongPacket(nonce) {
if (!(this instanceof PongPacket))
return new PongPacket(nonce);
Packet.call(this);
this.nonce = nonce || new bn(0);
}
utils.inherits(PongPacket, Packet);
PongPacket.prototype.cmd = 'pong';
PongPacket.prototype.type = exports.types.PONG;
/**
* Serialize pong packet.
* @returns {Buffer}
*/
PongPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
p.writeU64(this.nonce);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
PongPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
this.nonce = p.readU64();
return this;
};
/**
* Instantiate pong packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {VerackPacket}
*/
PongPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new PongPacket().fromRaw(data);
};
/**
* Alert Packet
* @exports AlertPacket
* @constructor
* @param {Object} options
* @property {Number} version
* @property {Number} relayUntil
* @property {Number} expiration
* @property {Number} id
* @property {Number} cancel
* @property {Number[]} cancels
* @property {Number} minVer
* @property {Number} maxVer
* @property {String[]} subVers
* @property {Number} priority
* @property {String} comment
* @property {String} statusBar
* @property {String?} reserved
* @property {Buffer?} signature - Payload signature.
*/
function AlertPacket(options) {
var ts;
if (!(this instanceof AlertPacket))
return new AlertPacket(options);
Packet.call(this);
ts = time.now() + 7 * 86400;
this.version = 1;
this.relayUntil = ts;
this.expiration = ts;
this.id = 1;
this.cancel = 0;
this.cancels = [];
this.minVer = 10000;
this.maxVer = constants.VERSION;
this.subVers = [];
this.priority = 100;
this.comment = '';
this.statusBar = '';
this.reserved = '';
this.signature = null;
this._payload = null;
this._hash = null;
if (options)
this.fromOptions(options);
}
utils.inherits(AlertPacket, Packet);
AlertPacket.prototype.cmd = 'alert';
AlertPacket.prototype.type = exports.types.ALERT;
/**
* Inject properties from options object.
* @private
* @param {Object} options
*/
AlertPacket.prototype.fromOptions = function fromOptions(options) {
if (options.version != null)
this.version = options.version;
if (options.relayUntil != null)
this.relayUntil = options.relayUntil;
if (options.expiration != null)
this.expiration = options.expiration;
if (options.id != null)
this.id = options.id;
if (options.cancel != null)
this.cancel = options.cancel;
if (options.cancels)
this.cancels = options.cancels;
if (options.minVer != null)
this.minVer = options.minVer;
if (options.maxVer != null)
this.maxVer = options.maxVer;
if (options.subVers)
this.subVers = options.subVers;
if (options.priority != null)
this.priority = options.priority;
if (options.comment != null)
this.comment = options.comment;
if (options.statusBar != null)
this.statusBar = options.statusBar;
if (options.reserved != null)
this.reserved = options.reserved;
this.signature = options.signature;
return this;
};
/**
* Instantiate alert packet from options.
* @param {Object} options
* @returns {AlertPacket}
*/
AlertPacket.fromOptions = function fromOptions(options) {
return new AlertPacket().fromOptions(options);
};
/**
* Get the hash256 of the alert payload.
* @param {String?} enc
* @returns {Hash}
*/
AlertPacket.prototype.hash = function hash(enc) {
if (!this._hash)
this._hash = crypto.hash256(this.toPayload());
return enc === 'hex' ? this._hash.toString('hex') : this._hash;
};
/**
* Serialize the packet to its payload.
* @returns {Buffer}
*/
AlertPacket.prototype.toPayload = function toPayload() {
if (!this._payload)
this._payload = this.framePayload();
return this._payload;
};
/**
* Sign the alert packet payload.
* @param {Buffer} key - Private key.
*/
AlertPacket.prototype.sign = function sign(key) {
this.signature = ec.sign(this.hash(), key);
};
/**
* Verify the alert packet.
* @param {Buffer} key - Public key.
* @returns {Boolean}
*/
AlertPacket.prototype.verify = function verify(key) {
return ec.verify(this.hash(), this.signature, key);
};
/**
* Serialize the alert packet (includes payload _and_ signature).
* @returns {Buffer}
*/
AlertPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
p.writeVarBytes(this.toPayload());
p.writeVarBytes(this.signature);
if (!writer)
p = p.render();
return p;
};
/**
* Serialize the alert packet payload.
* @private
* @returns {Buffer}
*/
AlertPacket.prototype.framePayload = function framePayload(writer) {
var p = BufferWriter(writer);
var i;
p.write32(this.version);
p.write64(this.relayUntil);
p.write64(this.expiration);
p.write32(this.id);
p.write32(this.cancel);
p.writeVarint(this.cancels.length);
for (i = 0; i < this.cancels.length; i++)
p.write32(this.cancels[i]);
p.write32(this.minVer);
p.write32(this.maxVer);
p.writeVarint(this.subVers.length);
for (i = 0; i < this.subVers.length; i++)
p.writeVarString(this.subVers[i], 'ascii');
p.write32(this.priority);
p.writeVarString(this.comment, 'ascii');
p.writeVarString(this.statusBar, 'ascii');
p.writeVarString(this.reserved, 'ascii');
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
AlertPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
var i, count;
this._payload = p.readVarBytes();
this.signature = p.readVarBytes();
p = BufferReader(this._payload);
this.version = p.read32();
this.relayUntil = p.read53();
this.expiration = p.read53();
this.id = p.read32();
this.cancel = p.read32();
count = p.readVarint();
for (i = 0; i < count; i++)
this.cancels.push(p.read32());
this.minVer = p.read32();
this.maxVer = p.read32();
count = p.readVarint();
for (i = 0; i < count; i++)
this.subVers.push(p.readVarString('ascii'));
this.priority = p.read32();
this.comment = p.readVarString('ascii');
this.statusBar = p.readVarString('ascii');
this.reserved = p.readVarString('ascii');
return this;
};
/**
* Instantiate alert packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {AlertPacket}
*/
AlertPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new AlertPacket().fromRaw(data, enc);
};
/**
* Represents a `getaddr` packet.
* @exports GetAddrPacket
* @constructor
*/
function GetAddrPacket() {
if (!(this instanceof GetAddrPacket))
return new GetAddrPacket();
Packet.call(this);
}
utils.inherits(GetAddrPacket, Packet);
GetAddrPacket.prototype.cmd = 'getaddr';
GetAddrPacket.prototype.type = exports.types.GETADDR;
/**
* Serialize getaddr packet.
* @returns {Buffer}
*/
GetAddrPacket.prototype.toRaw = function toRaw(writer) {
return writer || DUMMY;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
GetAddrPacket.prototype.fromRaw = function fromRaw(data) {
return this;
};
/**
* Instantiate getaddr packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {GetAddrPacket}
*/
GetAddrPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new GetAddrPacket().fromRaw(data);
};
/**
* Represents a `addr` packet.
* @exports AddrPacket
* @constructor
* @param {(NetworkAddress[])?} items
* @property {NetworkAddress[]} items
*/
function AddrPacket(items) {
if (!(this instanceof AddrPacket))
return new AddrPacket(items);
Packet.call(this);
this.items = items || [];
}
utils.inherits(AddrPacket, Packet);
AddrPacket.prototype.cmd = 'addr';
AddrPacket.prototype.type = exports.types.ADDR;
/**
* Serialize addr packet.
* @returns {Buffer}
*/
AddrPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
var i;
p.writeVarint(this.items.length);
for (i = 0; i < this.items.length; i++)
this.items[i].toRaw(true, p);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
AddrPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
var i, count;
count = p.readVarint();
for (i = 0; i < count; i++)
this.items.push(NetworkAddress.fromRaw(p, true));
return this;
};
/**
* Instantiate addr packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {AddrPacket}
*/
AddrPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new AddrPacket().fromRaw(data);
};
/**
* Represents a `inv` packet.
* @exports InvPacket
* @constructor
* @param {(InvItem[])?} items
* @property {InvItem[]} items
*/
function InvPacket(items) {
if (!(this instanceof InvPacket))
return new InvPacket(items);
Packet.call(this);
this.items = items || [];
}
utils.inherits(InvPacket, Packet);
InvPacket.prototype.cmd = 'inv';
InvPacket.prototype.type = exports.types.INV;
/**
* Serialize inv packet.
* @returns {Buffer}
*/
InvPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
var i;
p.writeVarint(this.items.length);
for (i = 0; i < this.items.length; i++)
this.items[i].toRaw(p);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
InvPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
var i, count;
count = p.readVarint();
for (i = 0; i < count; i++)
this.items.push(InvItem.fromRaw(p));
return this;
};
/**
* Instantiate inv packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {InvPacket}
*/
InvPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new InvPacket().fromRaw(data);
};
/**
* Represents a `getdata` packet.
* @exports GetDataPacket
* @extends InvPacket
* @constructor
* @param {(InvItem[])?} items
*/
function GetDataPacket(items) {
if (!(this instanceof GetDataPacket))
return new GetDataPacket(items);
InvPacket.call(this, items);
}
utils.inherits(GetDataPacket, InvPacket);
GetDataPacket.prototype.cmd = 'getdata';
GetDataPacket.prototype.type = exports.types.GETDATA;
/**
* Instantiate getdata packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {GetDataPacket}
*/
GetDataPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new GetDataPacket().fromRaw(data);
};
/**
* Represents a `notfound` packet.
* @exports NotFoundPacket
* @extends InvPacket
* @constructor
* @param {(InvItem[])?} items
*/
function NotFoundPacket(items) {
if (!(this instanceof NotFoundPacket))
return new NotFoundPacket(items);
InvPacket.call(this, items);
}
utils.inherits(NotFoundPacket, InvPacket);
NotFoundPacket.prototype.cmd = 'notfound';
NotFoundPacket.prototype.type = exports.types.NOTFOUND;
/**
* Instantiate notfound packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {NotFoundPacket}
*/
NotFoundPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new NotFoundPacket().fromRaw(data);
};
/**
* Represents a `getblocks` packet.
* @exports GetBlocksPacket
* @constructor
* @param {Hash[]} locator
* @param {Hash?} stop
* @property {Hash[]} locator
* @property {Hash|null} stop
*/
function GetBlocksPacket(locator, stop) {
if (!(this instanceof GetBlocksPacket))
return new GetBlocksPacket(locator, stop);
Packet.call(this);
this.version = constants.VERSION;
this.locator = locator || [];
this.stop = stop || null;
}
utils.inherits(GetBlocksPacket, Packet);
GetBlocksPacket.prototype.cmd = 'getblocks';
GetBlocksPacket.prototype.type = exports.types.GETBLOCKS;
/**
* Serialize getblocks packet.
* @returns {Buffer}
*/
GetBlocksPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
var i;
p.writeU32(this.version);
p.writeVarint(this.locator.length);
for (i = 0; i < this.locator.length; i++)
p.writeHash(this.locator[i]);
p.writeHash(this.stop || constants.ZERO_HASH);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
GetBlocksPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
var i, count;
this.version = p.readU32();
count = p.readVarint();
for (i = 0; i < count; i++)
this.locator.push(p.readHash('hex'));
this.stop = p.readHash('hex');
if (this.stop === constants.NULL_HASH)
this.stop = null;
return this;
};
/**
* Instantiate getblocks packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {GetBlocksPacket}
*/
GetBlocksPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new GetBlocksPacket().fromRaw(data);
};
/**
* Represents a `getheaders` packet.
* @exports GetHeadersPacket
* @extends GetBlocksPacket
* @constructor
* @param {Hash[]} locator
* @param {Hash?} stop
*/
function GetHeadersPacket(locator, stop) {
if (!(this instanceof GetHeadersPacket))
return new GetHeadersPacket(locator, stop);
GetBlocksPacket.call(this, locator, stop);
}
utils.inherits(GetHeadersPacket, GetBlocksPacket);
GetHeadersPacket.prototype.cmd = 'getheaders';
GetHeadersPacket.prototype.type = exports.types.GETHEADERS;
/**
* Instantiate getheaders packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {GetHeadersPacket}
*/
GetHeadersPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new GetHeadersPacket().fromRaw(data);
};
/**
* Represents a `headers` packet.
* @exports HeadersPacket
* @constructor
* @param {(Headers[])?} items
* @property {Headers[]} items
*/
function HeadersPacket(items) {
if (!(this instanceof HeadersPacket))
return new HeadersPacket(items);
Packet.call(this);
this.items = items || [];
}
utils.inherits(HeadersPacket, Packet);
HeadersPacket.prototype.cmd = 'headers';
HeadersPacket.prototype.type = exports.types.HEADERS;
/**
* Serialize headers packet.
* @returns {Buffer}
*/
HeadersPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
var i;
p.writeVarint(this.items.length);
for (i = 0; i < this.items.length; i++)
this.items[i].toRaw(p);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
HeadersPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
var i, count;
count = p.readVarint();
for (i = 0; i < count; i++)
this.items.push(Headers.fromRaw(p));
return this;
};
/**
* Instantiate headers packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {VerackPacket}
*/
HeadersPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new HeadersPacket().fromRaw(data);
};
/**
* Represents a `sendheaders` packet.
* @exports SendHeadersPacket
* @constructor
*/
function SendHeadersPacket() {
if (!(this instanceof SendHeadersPacket))
return new SendHeadersPacket();
Packet.call(this);
}
utils.inherits(SendHeadersPacket, Packet);
SendHeadersPacket.prototype.cmd = 'sendheaders';
SendHeadersPacket.prototype.type = exports.types.SENDHEADERS;
/**
* Serialize sendheaders packet.
* @returns {Buffer}
*/
SendHeadersPacket.prototype.toRaw = function toRaw(writer) {
return writer || DUMMY;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
SendHeadersPacket.prototype.fromRaw = function fromRaw(data) {
return this;
};
/**
* Instantiate sendheaders packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {SendHeadersPacket}
*/
SendHeadersPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new SendHeadersPacket().fromRaw(data);
};
/**
* Represents a `block` packet.
* @exports BlockPacket
* @constructor
* @param {Block|null} block
* @param {Boolean?} witness
* @property {Block} block
* @property {Boolean} witness
*/
function BlockPacket(block, witness) {
if (!(this instanceof BlockPacket))
return new BlockPacket(block, witness);
Packet.call(this);
this.block = block || new MemBlock();
this.witness = witness || false;
}
utils.inherits(BlockPacket, Packet);
BlockPacket.prototype.cmd = 'block';
BlockPacket.prototype.type = exports.types.BLOCK;
/**
* Serialize block packet.
* @returns {Buffer}
*/
BlockPacket.prototype.toRaw = function toRaw(writer) {
if (this.witness)
return this.block.toRaw(writer);
return this.block.toNormal(writer);
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
BlockPacket.prototype.fromRaw = function fromRaw(data) {
this.block.fromRaw(data);
return this;
};
/**
* Instantiate block packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {BlockPacket}
*/
BlockPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new BlockPacket().fromRaw(data);
};
/**
* Represents a `tx` packet.
* @exports TXPacket
* @constructor
* @param {TX|null} tx
* @param {Boolean?} witness
* @property {TX} block
* @property {Boolean} witness
*/
function TXPacket(tx, witness) {
if (!(this instanceof TXPacket))
return new TXPacket(tx, witness);
Packet.call(this);
this.tx = tx || new TX();
this.witness = witness || false;
}
utils.inherits(TXPacket, Packet);
TXPacket.prototype.cmd = 'tx';
TXPacket.prototype.type = exports.types.TX;
/**
* Serialize tx packet.
* @returns {Buffer}
*/
TXPacket.prototype.toRaw = function toRaw(writer) {
if (this.witness)
return this.tx.toRaw(writer);
return this.tx.toNormal(writer);
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
TXPacket.prototype.fromRaw = function fromRaw(data) {
this.tx.fromRaw(data);
return this;
};
/**
* Instantiate tx packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {TXPacket}
*/
TXPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new TXPacket().fromRaw(data);
};
/**
* Reject Packet
* @exports RejectPacket
* @constructor
* @property {(Number|String)?} code - Code
* (see {@link constants.reject}).
* @property {String?} msg - Message.
* @property {String?} reason - Reason.
* @property {(Hash|Buffer)?} data - Transaction or block hash.
*/
function RejectPacket(options) {
if (!(this instanceof RejectPacket))
return new RejectPacket(options);
Packet.call(this);
this.message = '';
this.code = constants.reject.INVALID;
this.reason = '';
this.data = null;
if (options)
this.fromOptions(options);
}
utils.inherits(RejectPacket, Packet);
RejectPacket.prototype.cmd = 'reject';
RejectPacket.prototype.type = exports.types.REJECT;
/**
* Inject properties from options object.
* @private
* @param {Object} options
*/
RejectPacket.prototype.fromOptions = function fromOptions(options) {
var code = options.code;
if (options.message)
this.message = options.message;
if (code != null) {
if (typeof code === 'string')
code = constants.reject[code.toUpperCase()];
if (code >= constants.reject.INTERNAL)
code = constants.reject.INVALID;
this.code = code;
}
if (options.reason)
this.reason = options.reason;
if (options.data)
this.data = options.data;
return this;
};
/**
* Instantiate reject packet from options.
* @param {Object} options
* @returns {RejectPacket}
*/
RejectPacket.fromOptions = function fromOptions(options) {
return new RejectPacket().fromOptions(options);
};
/**
* Serialize reject packet.
* @returns {Buffer}
*/
RejectPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
assert(this.message.length <= 12);
assert(this.reason.length <= 111);
p.writeVarString(this.message, 'ascii');
p.writeU8(this.code);
p.writeVarString(this.reason, 'ascii');
if (this.data)
p.writeHash(this.data);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
RejectPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
this.message = p.readVarString('ascii', 12);
this.code = p.readU8();
this.reason = p.readVarString('ascii', 111);
if (this.message === 'block' || this.message === 'tx')
this.data = p.readHash('hex');
else
this.data = null;
return this;
};
/**
* Instantiate reject packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {RejectPacket}
*/
RejectPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new RejectPacket().fromRaw(data, enc);
};
/**
* Inject properties from reason message and object.
* @private
* @param {Number} code
* @param {String} reason
* @param {(TX|Block)?} obj
*/
RejectPacket.prototype.fromReason = function fromReason(code, reason, obj) {
if (typeof code === 'string')
code = constants.reject[code.toUpperCase()];
if (!code)
code = constants.reject.INVALID;
if (code >= constants.reject.INTERNAL)
code = constants.reject.INVALID;
this.message = '';
this.code = code;
this.reason = reason;
if (obj) {
this.message = (obj instanceof TX) ? 'tx' : 'block';
this.data = obj.hash('hex');
}
return this;
};
/**
* Instantiate reject packet from reason message.
* @param {Number} code
* @param {String} reason
* @param {(TX|Block)?} obj
* @returns {RejectPacket}
*/
RejectPacket.fromReason = function fromReason(code, reason, obj) {
return new RejectPacket().fromReason(code, reason, obj);
};
/**
* Instantiate reject packet from verify error.
* @param {VerifyError} err
* @param {(TX|Block)?} obj
* @returns {RejectPacket}
*/
RejectPacket.fromError = function fromError(err, obj) {
return RejectPacket.fromReason(err.code, err.reason, obj);
};
/**
* Inspect reject packet.
* @returns {String}
*/
RejectPacket.prototype.inspect = function inspect() {
return '<Reject:'
+ ' msg=' + this.message
+ ' code=' + (constants.rejectByVal[this.code] || this.code)
+ ' reason=' + this.reason
+ ' data=' + this.data
+ '>';
};
/**
* Represents a `mempool` packet.
* @exports MempoolPacket
* @constructor
*/
function MempoolPacket() {
if (!(this instanceof MempoolPacket))
return new MempoolPacket();
Packet.call(this);
}
utils.inherits(MempoolPacket, Packet);
MempoolPacket.prototype.cmd = 'mempool';
MempoolPacket.prototype.type = exports.types.MEMPOOL;
/**
* Serialize mempool packet.
* @returns {Buffer}
*/
MempoolPacket.prototype.toRaw = function toRaw(writer) {
return writer || DUMMY;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
MempoolPacket.prototype.fromRaw = function fromRaw(data) {
return this;
};
/**
* Instantiate mempool packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {VerackPacket}
*/
MempoolPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new MempoolPacket().fromRaw(data);
};
/**
* Represents a `filterload` packet.
* @exports FilterLoadPacket
* @constructor
* @param {Buffer|null} filter
* @param {Number|null} n
* @param {Number|null} tweak
* @param {Number|null} update
* @property {Buffer} filter
* @property {Number} n
* @property {Number} tweak
* @property {Number} update
*/
function FilterLoadPacket(filter, n, tweak, update) {
if (!(this instanceof FilterLoadPacket))
return new FilterLoadPacket(filter, n, tweak, update);
Packet.call(this);
if (filter instanceof Bloom) {
this.fromFilter(filter);
} else {
this.filter = filter || DUMMY;
this.n = n || 0;
this.tweak = tweak || 0;
this.update = update || 0;
}
}
utils.inherits(FilterLoadPacket, Packet);
FilterLoadPacket.prototype.cmd = 'filterload';
FilterLoadPacket.prototype.type = exports.types.FILTERLOAD;
/**
* Serialize filterload packet.
* @returns {Buffer}
*/
FilterLoadPacket.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;
};
/**
* Serialize filterload packet.
* @returns {Buffer}
*/
FilterLoadPacket.prototype.toFilter = function toFilter() {
return new Bloom(this.filter, this.n, this.tweak, this.update);
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
FilterLoadPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
this.filter = p.readVarBytes();
this.n = p.readU32();
this.tweak = p.readU32();
this.update = p.readU8();
assert(constants.filterFlagsByVal[this.update] != null, 'Bad filter flag.');
return this;
};
/**
* Inject properties from bloom filter.
* @private
* @param {Bloom} filter
*/
FilterLoadPacket.prototype.fromFilter = function fromFilter(filter) {
this.filter = filter.filter;
this.n = filter.n;
this.tweak = filter.tweak;
this.update = filter.update;
return this;
};
/**
* Instantiate filterload packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {FilterLoadPacket}
*/
FilterLoadPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new FilterLoadPacket().fromRaw(data);
};
/**
* Instantiate filterload packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {FilterLoadPacket}
*/
FilterLoadPacket.fromFilter = function fromFilter(filter) {
return new FilterLoadPacket().fromFilter(filter);
};
/**
* Ensure the filter is within the size limits.
* @returns {Boolean}
*/
FilterLoadPacket.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;
};
/**
* Represents a `filteradd` packet.
* @exports FilterAddPacket
* @constructor
* @param {Buffer?} data
* @property {Buffer} data
*/
function FilterAddPacket(data) {
if (!(this instanceof FilterAddPacket))
return new FilterAddPacket(data);
Packet.call(this);
this.data = data || DUMMY;
}
utils.inherits(FilterAddPacket, Packet);
FilterAddPacket.prototype.cmd = 'filteradd';
FilterAddPacket.prototype.type = exports.types.FILTERADD;
/**
* Serialize filteradd packet.
* @returns {Buffer}
*/
FilterAddPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
p.writeVarBytes(this.data);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
FilterAddPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
this.data = p.readVarBytes();
return this;
};
/**
* Instantiate filteradd packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {FilterAddPacket}
*/
FilterAddPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new FilterAddPacket().fromRaw(data);
};
/**
* Represents a `filterclear` packet.
* @exports FilterClearPacket
* @constructor
*/
function FilterClearPacket() {
if (!(this instanceof FilterClearPacket))
return new FilterClearPacket();
Packet.call(this);
}
utils.inherits(FilterClearPacket, Packet);
FilterClearPacket.prototype.cmd = 'filterclear';
FilterClearPacket.prototype.type = exports.types.FILTERCLEAR;
/**
* Serialize filterclear packet.
* @returns {Buffer}
*/
FilterClearPacket.prototype.toRaw = function toRaw(writer) {
return writer || DUMMY;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
FilterClearPacket.prototype.fromRaw = function fromRaw(data) {
return this;
};
/**
* Instantiate filterclear packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {FilterClearPacket}
*/
FilterClearPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new FilterClearPacket().fromRaw(data);
};
/**
* Represents a `merkleblock` packet.
* @exports MerkleBlockPacket
* @constructor
* @param {MerkleBlock?} block
* @property {MerkleBlock} block
*/
function MerkleBlockPacket(block) {
if (!(this instanceof MerkleBlockPacket))
return new MerkleBlockPacket(block);
Packet.call(this);
this.block = block || new MerkleBlock();
}
utils.inherits(MerkleBlockPacket, Packet);
MerkleBlockPacket.prototype.cmd = 'merkleblock';
MerkleBlockPacket.prototype.type = exports.types.MERKLEBLOCK;
/**
* Serialize merkleblock packet.
* @returns {Buffer}
*/
MerkleBlockPacket.prototype.toRaw = function toRaw(writer) {
return this.block.toRaw(writer);
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
MerkleBlockPacket.prototype.fromRaw = function fromRaw(data) {
this.block.fromRaw(data);
return this;
};
/**
* Instantiate merkleblock packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {MerkleBlockPacket}
*/
MerkleBlockPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new MerkleBlockPacket().fromRaw(data);
};
/**
* Represents a `getutxos` packet.
* @exports GetUTXOsPacket
* @constructor
* @param {Boolean} mempool
* @param {Outpoint[]} prevout
* @property {Boolean} mempool
* @property {Outpoint[]} prevout
*/
function GetUTXOsPacket(mempool, prevout) {
if (!(this instanceof GetUTXOsPacket))
return new GetUTXOsPacket(mempool, prevout);
Packet.call(this);
this.mempool = mempool || false;
this.prevout = prevout || [];
}
utils.inherits(GetUTXOsPacket, Packet);
GetUTXOsPacket.prototype.cmd = 'getutxos';
GetUTXOsPacket.prototype.type = exports.types.GETUTXOS;
/**
* Serialize getutxos packet.
* @returns {Buffer}
*/
GetUTXOsPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
var i;
p.writeU8(this.mempool ? 1 : 0);
p.writeVarint(this.prevout.length);
for (i = 0; i < this.prevout.length; i++)
this.prevout[i].toRaw(p);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
GetUTXOsPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
var i, count;
this.mempool = p.readU8() === 1;
count = p.readVarint();
for (i = 0; i < count; i++)
this.prevout.push(Outpoint.fromRaw(p));
return this;
};
/**
* Instantiate getutxos packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {GetBlocksPacket}
*/
GetUTXOsPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new GetUTXOsPacket().fromRaw(data);
};
/**
* Represents a `utxos` packet.
* @exports UTXOsPacket
* @constructor
* @param {Object} options
* @property {Number} height
* @property {Hash} tip
* @property {Boolean[]} hits
* @property {Coin[]} coins
*/
function UTXOsPacket(options) {
if (!(this instanceof UTXOsPacket))
return new UTXOsPacket(options);
Packet.call(this);
this.height = -1;
this.tip = constants.NULL_HASH;
this.hits = [];
this.coins = [];
if (options)
this.fromOptions(options);
}
utils.inherits(UTXOsPacket, Packet);
UTXOsPacket.prototype.cmd = 'utxos';
UTXOsPacket.prototype.type = exports.types.UTXOS;
/**
* Inject properties from options.
* @private
* @param {Buffer} data
*/
UTXOsPacket.prototype.fromOptions = function fromOptions(options) {
if (options.height != null) {
assert(utils.isNumber(options.height));
this.height = options.height;
}
if (options.tip) {
assert(typeof options.tip === 'string');
this.tip = options.tip;
}
if (options.hits) {
assert(Array.isArray(options.hits));
this.hits = options.hits;
}
if (options.coins) {
assert(Array.isArray(options.coins));
this.coins = options.coins;
}
return this;
};
/**
* Instantiate utxos packet from options.
* @param {Buffer} data
* @param {String?} enc
* @returns {GetBlocksPacket}
*/
UTXOsPacket.fromOptions = function fromOptions(options) {
return new UTXOsPacket().fromOptions(options);
};
/**
* Serialize utxos packet.
* @returns {Buffer}
*/
UTXOsPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
var map = new Buffer((this.hits.length + 7) / 8 | 0);
var i, bit, oct, coin, height;
for (i = 0; i < this.hits.length; i++) {
bit = i % 8;
oct = (i - bit) / 8;
map[oct] |= +this.hits[i] << (7 - bit);
}
p.writeU32(this.height);
p.writeHash(this.tip);
p.writeVarBytes(map);
p.writeVarInt(this.coins.length);
for (i = 0; i < this.coins.length; i++) {
coin = this.coins[i];
height = coin.height;
if (height === -1)
height = 0x7fffffff;
p.writeU32(coin.version);
p.writeU32(height);
p.write64(coin.value);
p.writeVarBytes(coin.script.toRaw());
}
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
UTXOsPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
var i, bit, oct, coin, output;
var version, height, map, count;
this.height = p.readU32();
this.tip = p.readHash('hex');
map = p.readVarBytes();
count = p.readVarint();
for (i = 0; i < map.length * 8; i++) {
bit = i % 8;
oct = (i - bit) / 8;
this.hits.push((map[oct] >> (7 - bit)) & 1);
}
for (i = 0; i < count; i++) {
version = p.readU32();
height = p.readU32();
coin = new Coin();
if (height === 0x7fffffff)
height = -1;
output = Output.fromRaw(p);
coin.version = version;
coin.height = height;
coin.script = output.script;
coin.value = output.value;
this.coins.push(coin);
}
return this;
};
/**
* Instantiate utxos packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {UTXOsPacket}
*/
UTXOsPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new UTXOsPacket().fromRaw(data);
};
/**
* Represents a `havewitness` packet.
* @exports HaveWitnessPacket
* @constructor
*/
function HaveWitnessPacket() {
if (!(this instanceof HaveWitnessPacket))
return new HaveWitnessPacket();
Packet.call(this);
}
utils.inherits(HaveWitnessPacket, Packet);
HaveWitnessPacket.prototype.cmd = 'havewitness';
HaveWitnessPacket.prototype.type = exports.types.HAVEWITNESS;
/**
* Serialize havewitness packet.
* @returns {Buffer}
*/
HaveWitnessPacket.prototype.toRaw = function toRaw(writer) {
return writer || DUMMY;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
HaveWitnessPacket.prototype.fromRaw = function fromRaw(data) {
return this;
};
/**
* Instantiate havewitness packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {HaveWitnessPacket}
*/
HaveWitnessPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new HaveWitnessPacket().fromRaw(data);
};
/**
* Represents a `feefilter` packet.
* @exports FeeFilterPacket
* @constructor
* @param {Rate?} rate
* @property {Rate} rate
*/
function FeeFilterPacket(rate) {
if (!(this instanceof FeeFilterPacket))
return new FeeFilterPacket(rate);
Packet.call(this);
this.rate = rate || 0;
}
utils.inherits(FeeFilterPacket, Packet);
FeeFilterPacket.prototype.cmd = 'feefilter';
FeeFilterPacket.prototype.type = exports.types.FEEFILTER;
/**
* Serialize feefilter packet.
* @returns {Buffer}
*/
FeeFilterPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
p.write64(this.rate);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
FeeFilterPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
this.rate = p.read64N();
return this;
};
/**
* Instantiate feefilter packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {FeeFilterPacket}
*/
FeeFilterPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new FeeFilterPacket().fromRaw(data);
};
/**
* Represents a `sendcmpct` packet.
* @exports SendCmpctPacket
* @constructor
* @param {Number|null} mode
* @param {Number|null} version
* @property {Number} mode
* @property {Number} version
*/
function SendCmpctPacket(mode, version) {
if (!(this instanceof SendCmpctPacket))
return new SendCmpctPacket(mode, version);
Packet.call(this);
this.mode = mode || 0;
this.version = version || 1;
}
utils.inherits(SendCmpctPacket, Packet);
SendCmpctPacket.prototype.cmd = 'sendcmpct';
SendCmpctPacket.prototype.type = exports.types.SENDCMPCT;
/**
* Serialize sendcmpct packet.
* @returns {Buffer}
*/
SendCmpctPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
p.writeU8(this.mode);
p.writeU64(this.version);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
SendCmpctPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
this.mode = p.readU8();
this.version = p.readU53();
return this;
};
/**
* Instantiate sendcmpct packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {SendCmpctPacket}
*/
SendCmpctPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new SendCmpctPacket().fromRaw(data);
};
/**
* Represents a `cmpctblock` packet.
* @exports CmpctBlockPacket
* @constructor
* @param {Block|null} block
* @param {Boolean|null} witness
* @property {Block} block
* @property {Boolean} witness
*/
function CmpctBlockPacket(block, witness) {
if (!(this instanceof CmpctBlockPacket))
return new CmpctBlockPacket(block, witness);
Packet.call(this);
this.block = block || new bip152.CompactBlock();
this.witness = witness || false;
}
utils.inherits(CmpctBlockPacket, Packet);
CmpctBlockPacket.prototype.cmd = 'cmpctblock';
CmpctBlockPacket.prototype.type = exports.types.CMPCTBLOCK;
/**
* Serialize cmpctblock packet.
* @returns {Buffer}
*/
CmpctBlockPacket.prototype.toRaw = function toRaw(writer) {
if (this.witness)
return this.block.toRaw(writer);
return this.block.toNormal(writer);
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
CmpctBlockPacket.prototype.fromRaw = function fromRaw(data) {
this.block.fromRaw(data);
return this;
};
/**
* Instantiate cmpctblock packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {CmpctBlockPacket}
*/
CmpctBlockPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new CmpctBlockPacket().fromRaw(data);
};
/**
* Represents a `getblocktxn` packet.
* @exports GetBlockTxnPacket
* @constructor
* @param {TXRequest?} request
* @property {TXRequest} request
*/
function GetBlockTxnPacket(request) {
if (!(this instanceof GetBlockTxnPacket))
return new GetBlockTxnPacket(request);
Packet.call(this);
this.request = request || new bip152.TXRequest();
}
utils.inherits(GetBlockTxnPacket, Packet);
GetBlockTxnPacket.prototype.cmd = 'getblocktxn';
GetBlockTxnPacket.prototype.type = exports.types.GETBLOCKTXN;
/**
* Serialize getblocktxn packet.
* @returns {Buffer}
*/
GetBlockTxnPacket.prototype.toRaw = function toRaw(writer) {
return this.request.toRaw(writer);
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
GetBlockTxnPacket.prototype.fromRaw = function fromRaw(data) {
this.request.fromRaw(data);
return this;
};
/**
* Instantiate getblocktxn packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {GetBlockTxnPacket}
*/
GetBlockTxnPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new GetBlockTxnPacket().fromRaw(data);
};
/**
* Represents a `blocktxn` packet.
* @exports BlockTxnPacket
* @constructor
* @param {TXResponse?} response
* @param {Boolean?} witness
* @property {TXResponse} response
* @property {Boolean} witness
*/
function BlockTxnPacket(response, witness) {
if (!(this instanceof BlockTxnPacket))
return new BlockTxnPacket(response, witness);
Packet.call(this);
this.response = response || new bip152.TXResponse();
this.witness = witness || false;
}
utils.inherits(BlockTxnPacket, Packet);
BlockTxnPacket.prototype.cmd = 'blocktxn';
BlockTxnPacket.prototype.type = exports.types.BLOCKTXN;
/**
* Serialize blocktxn packet.
* @returns {Buffer}
*/
BlockTxnPacket.prototype.toRaw = function toRaw(writer) {
if (this.witness)
return this.response.toRaw(writer);
return this.response.toNormal(writer);
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
BlockTxnPacket.prototype.fromRaw = function fromRaw(data) {
this.response.fromRaw(data);
return this;
};
/**
* Instantiate blocktxn packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {BlockTxnPacket}
*/
BlockTxnPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new BlockTxnPacket().fromRaw(data);
};
/**
* Represents a `encinit` packet.
* @exports EncinitPacket
* @constructor
* @param {Buffer|null} publicKey
* @param {Number|null} cipher
* @property {Buffer} publicKey
* @property {Number} cipher
*/
function EncinitPacket(publicKey, cipher) {
if (!(this instanceof EncinitPacket))
return new EncinitPacket(publicKey, cipher);
Packet.call(this);
this.publicKey = publicKey || constants.ZERO_KEY;
this.cipher = cipher || 0;
}
utils.inherits(EncinitPacket, Packet);
EncinitPacket.prototype.cmd = 'encinit';
EncinitPacket.prototype.type = exports.types.ENCINIT;
/**
* Serialize encinit packet.
* @returns {Buffer}
*/
EncinitPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
p.writeBytes(this.publicKey);
p.writeU8(this.cipher);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
EncinitPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
this.publicKey = p.readBytes(33);
this.cipher = p.readU8();
return this;
};
/**
* Instantiate getblocks packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {EncinitPacket}
*/
EncinitPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new EncinitPacket().fromRaw(data);
};
/**
* Represents a `encack` packet.
* @exports EncackPacket
* @constructor
* @param {Buffer?} publicKey
* @property {Buffer} publicKey
*/
function EncackPacket(publicKey) {
if (!(this instanceof EncackPacket))
return new EncackPacket(publicKey);
Packet.call(this);
this.publicKey = publicKey || constants.ZERO_KEY;
}
utils.inherits(EncackPacket, Packet);
EncackPacket.prototype.cmd = 'encack';
EncackPacket.prototype.type = exports.types.ENCACK;
/**
* Serialize encack packet.
* @returns {Buffer}
*/
EncackPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
p.writeBytes(this.publicKey);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
EncackPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
this.publicKey = p.readBytes(33);
return this;
};
/**
* Instantiate encack packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {EncackPacket}
*/
EncackPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new EncackPacket().fromRaw(data);
};
/**
* Represents a `authchallenge` packet.
* @exports AuthChallengePacket
* @constructor
* @param {Buffer?} hash
* @property {Buffer} hash
*/
function AuthChallengePacket(hash) {
if (!(this instanceof AuthChallengePacket))
return new AuthChallengePacket(hash);
Packet.call(this);
this.hash = hash || constants.ZERO_HASH;
}
utils.inherits(AuthChallengePacket, Packet);
AuthChallengePacket.prototype.cmd = 'authchallenge';
AuthChallengePacket.prototype.type = exports.types.AUTHCHALLENGE;
/**
* Serialize authchallenge packet.
* @returns {Buffer}
*/
AuthChallengePacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
p.writeBytes(this.hash);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
AuthChallengePacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
this.hash = p.readHash();
return this;
};
/**
* Instantiate authchallenge packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {AuthChallengePacket}
*/
AuthChallengePacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new AuthChallengePacket().fromRaw(data);
};
/**
* Represents a `authreply` packet.
* @exports AuthReplyPacket
* @constructor
* @param {Buffer?} signature
* @property {Buffer} signature
*/
function AuthReplyPacket(signature) {
if (!(this instanceof AuthReplyPacket))
return new AuthReplyPacket(signature);
Packet.call(this);
this.signature = signature || constants.ZERO_SIG64;
}
utils.inherits(AuthReplyPacket, Packet);
AuthReplyPacket.prototype.cmd = 'authreply';
AuthReplyPacket.prototype.type = exports.types.AUTHREPLY;
/**
* Serialize authreply packet.
* @returns {Buffer}
*/
AuthReplyPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
p.writeBytes(this.signature);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
AuthReplyPacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
this.signature = p.readBytes(64);
return this;
};
/**
* Instantiate authreply packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {AuthReplyPacket}
*/
AuthReplyPacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new AuthReplyPacket().fromRaw(data);
};
/**
* Represents a `authpropose` packet.
* @exports AuthProposePacket
* @constructor
* @param {Hash?} hash
* @property {Hash} hash
*/
function AuthProposePacket(hash) {
if (!(this instanceof AuthProposePacket))
return new AuthProposePacket(hash);
Packet.call(this);
this.hash = hash || constants.ZERO_HASH;
}
utils.inherits(AuthProposePacket, Packet);
AuthProposePacket.prototype.cmd = 'authpropose';
AuthProposePacket.prototype.type = exports.types.AUTHPROPOSE;
/**
* Serialize authpropose packet.
* @returns {Buffer}
*/
AuthProposePacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
p.writeBytes(this.hash);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
AuthProposePacket.prototype.fromRaw = function fromRaw(data) {
var p = BufferReader(data);
this.hash = p.readHash();
return this;
};
/**
* Instantiate authpropose packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {AuthProposePacket}
*/
AuthProposePacket.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new AuthProposePacket().fromRaw(data);
};
/**
* Represents an unknown packet.
* @exports UnknownPacket
* @constructor
* @param {String|null} cmd
* @param {Buffer|null} data
* @property {String} cmd
* @property {Buffer} data
*/
function UnknownPacket(cmd, data) {
if (!(this instanceof UnknownPacket))
return new UnknownPacket(cmd, data);
Packet.call(this);
this.cmd = cmd;
this.data = data;
}
utils.inherits(UnknownPacket, Packet);
UnknownPacket.prototype.type = exports.types.UNKNOWN;
/**
* Serialize unknown packet.
* @returns {Buffer}
*/
UnknownPacket.prototype.toRaw = function toRaw(writer) {
var p = BufferWriter(writer);
p.writeBytes(this.data);
if (!writer)
p = p.render();
return p;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
UnknownPacket.prototype.fromRaw = function fromRaw(cmd, data) {
assert(Buffer.isBuffer(data));
this.cmd = cmd;
this.data = data;
return this;
};
/**
* Instantiate unknown packet from serialized data.
* @param {Buffer} data
* @param {String?} enc
* @returns {UnknownPacket}
*/
UnknownPacket.fromRaw = function fromRaw(cmd, data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new UnknownPacket().fromRaw(cmd, data);
};
/**
* Parse a payload.
* @param {String} cmd
* @param {Buffer} data
* @returns {Packet}
*/
exports.fromRaw = function fromRaw(cmd, data) {
switch (cmd) {
case 'version':
return VersionPacket.fromRaw(data);
case 'verack':
return VerackPacket.fromRaw(data);
case 'ping':
return PingPacket.fromRaw(data);
case 'pong':
return PongPacket.fromRaw(data);
case 'alert':
return AlertPacket.fromRaw(data);
case 'getaddr':
return GetAddrPacket.fromRaw(data);
case 'addr':
return AddrPacket.fromRaw(data);
case 'inv':
return InvPacket.fromRaw(data);
case 'getdata':
return GetDataPacket.fromRaw(data);
case 'notfound':
return NotFoundPacket.fromRaw(data);
case 'getblocks':
return GetBlocksPacket.fromRaw(data);
case 'getheaders':
return GetHeadersPacket.fromRaw(data);
case 'headers':
return HeadersPacket.fromRaw(data);
case 'sendheaders':
return SendHeadersPacket.fromRaw(data);
case 'block':
return BlockPacket.fromRaw(data);
case 'tx':
return TXPacket.fromRaw(data);
case 'reject':
return RejectPacket.fromRaw(data);
case 'mempool':
return MempoolPacket.fromRaw(data);
case 'filterload':
return FilterLoadPacket.fromRaw(data);
case 'filteradd':
return FilterAddPacket.fromRaw(data);
case 'filterclear':
return FilterClearPacket.fromRaw(data);
case 'merkleblock':
return MerkleBlockPacket.fromRaw(data);
case 'getutxos':
return GetUTXOsPacket.fromRaw(data);
case 'utxos':
return UTXOsPacket.fromRaw(data);
case 'havewitness':
return HaveWitnessPacket.fromRaw(data);
case 'feefilter':
return FeeFilterPacket.fromRaw(data);
case 'sendcmpct':
return SendCmpctPacket.fromRaw(data);
case 'cmpctblock':
return CmpctBlockPacket.fromRaw(data);
case 'getblocktxn':
return GetBlockTxnPacket.fromRaw(data);
case 'blocktxn':
return BlockTxnPacket.fromRaw(data);
case 'encinit':
return EncinitPacket.fromRaw(data);
case 'encack':
return EncackPacket.fromRaw(data);
case 'authchallenge':
return AuthChallengePacket.fromRaw(data);
case 'authreply':
return AuthReplyPacket.fromRaw(data);
case 'authpropose':
return AuthProposePacket.fromRaw(data);
default:
return UnknownPacket.fromRaw(cmd, data);
}
};
/*
* Expose
*/
exports.Packet = Packet;
exports.VersionPacket = VersionPacket;
exports.VerackPacket = VerackPacket;
exports.PingPacket = PingPacket;
exports.PongPacket = PongPacket;
exports.AlertPacket = AlertPacket;
exports.GetAddrPacket = GetAddrPacket;
exports.AddrPacket = AddrPacket;
exports.InvPacket = InvPacket;
exports.GetDataPacket = GetDataPacket;
exports.NotFoundPacket = NotFoundPacket;
exports.GetBlocksPacket = GetBlocksPacket;
exports.GetHeadersPacket = GetHeadersPacket;
exports.HeadersPacket = HeadersPacket;
exports.SendHeadersPacket = SendHeadersPacket;
exports.BlockPacket = BlockPacket;
exports.TXPacket = TXPacket;
exports.RejectPacket = RejectPacket;
exports.MempoolPacket = MempoolPacket;
exports.FilterLoadPacket = FilterLoadPacket;
exports.FilterAddPacket = FilterAddPacket;
exports.FilterClearPacket = FilterClearPacket;
exports.MerkleBlockPacket = MerkleBlockPacket;
exports.GetUTXOsPacket = GetUTXOsPacket;
exports.UTXOsPacket = UTXOsPacket;
exports.HaveWitnessPacket = HaveWitnessPacket;
exports.FeeFilterPacket = FeeFilterPacket;
exports.SendCmpctPacket = SendCmpctPacket;
exports.CmpctBlockPacket = CmpctBlockPacket;
exports.GetBlockTxnPacket = GetBlockTxnPacket;
exports.BlockTxnPacket = BlockTxnPacket;
exports.EncinitPacket = EncinitPacket;
exports.EncackPacket = EncackPacket;
exports.AuthChallengePacket = AuthChallengePacket;
exports.AuthReplyPacket = AuthReplyPacket;
exports.AuthProposePacket = AuthProposePacket;
exports.UnknownPacket = UnknownPacket;