Moved block and version messages and shared utils into seperate files.
This commit is contained in:
parent
608e41de07
commit
6ca2f6982c
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
var Message = require('./message');
|
var Message = require('./message');
|
||||||
var BloomFilter = require('../bloomfilter');
|
var BloomFilter = require('../bloomfilter');
|
||||||
var packageInfo = require('../../package.json');
|
|
||||||
var inherits = require('util').inherits;
|
var inherits = require('util').inherits;
|
||||||
var bitcore = require('bitcore');
|
var bitcore = require('bitcore');
|
||||||
var BN = bitcore.crypto.BN;
|
var BN = bitcore.crypto.BN;
|
||||||
@ -11,6 +11,7 @@ var BufferWriter = bitcore.encoding.BufferWriter;
|
|||||||
var BufferUtil = bitcore.util.buffer;
|
var BufferUtil = bitcore.util.buffer;
|
||||||
var $ = bitcore.util.preconditions;
|
var $ = bitcore.util.preconditions;
|
||||||
var _ = bitcore.deps._;
|
var _ = bitcore.deps._;
|
||||||
|
var utils = require('./utils');
|
||||||
|
|
||||||
function builder(options) {
|
function builder(options) {
|
||||||
/* jshint maxstatements: 150 */
|
/* jshint maxstatements: 150 */
|
||||||
@ -46,192 +47,7 @@ function builder(options) {
|
|||||||
commands: commands
|
commands: commands
|
||||||
};
|
};
|
||||||
|
|
||||||
/* shared */
|
commands.version = require('./commands/version')({magicNumber: magicNumber});
|
||||||
|
|
||||||
function checkFinished(parser) {
|
|
||||||
if(!parser.finished()) {
|
|
||||||
throw new Error('Data still available after parsing');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNonce() {
|
|
||||||
return bitcore.crypto.Random.getRandomBuffer(8);
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeIP(ip, bw) {
|
|
||||||
var words = ip.v6.split(':').map(function(s) {
|
|
||||||
return new Buffer(s, 'hex');
|
|
||||||
});
|
|
||||||
for (var i = 0; i < words.length; i++) {
|
|
||||||
var word = words[i];
|
|
||||||
bw.write(word);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeAddr(addr, bw) {
|
|
||||||
if (_.isUndefined(addr)) {
|
|
||||||
var pad = new Buffer(Array(26));
|
|
||||||
bw.write(pad);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bw.writeUInt64LEBN(addr.services);
|
|
||||||
writeIP(addr.ip, bw);
|
|
||||||
bw.writeUInt16BE(addr.port);
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeInventory(inventory, bw) {
|
|
||||||
bw.writeVarintNum(inventory.length);
|
|
||||||
inventory.forEach(function(value) {
|
|
||||||
bw.writeUInt32LE(value.type);
|
|
||||||
bw.write(value.hash);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseIP(parser) {
|
|
||||||
var ipv6 = [];
|
|
||||||
var ipv4 = [];
|
|
||||||
for (var a = 0; a < 8; a++) {
|
|
||||||
var word = parser.read(2);
|
|
||||||
ipv6.push(word.toString('hex'));
|
|
||||||
if (a >= 6) {
|
|
||||||
ipv4.push(word[0]);
|
|
||||||
ipv4.push(word[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ipv6 = ipv6.join(':');
|
|
||||||
ipv4 = ipv4.join('.');
|
|
||||||
return {
|
|
||||||
v6: ipv6,
|
|
||||||
v4: ipv4
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseAddr(parser) {
|
|
||||||
var services = parser.readUInt64LEBN();
|
|
||||||
var ip = parseIP(parser);
|
|
||||||
var port = parser.readUInt16BE();
|
|
||||||
return {
|
|
||||||
services: services,
|
|
||||||
ip: ip,
|
|
||||||
port: port
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function sanitizeStartStop(obj) {
|
|
||||||
/* jshint maxcomplexity: 10 */
|
|
||||||
$.checkArgument(_.isUndefined(options.starts) || _.isArray(options.starts));
|
|
||||||
var starts = obj.starts;
|
|
||||||
var stop = obj.stop;
|
|
||||||
if (starts) {
|
|
||||||
starts = starts.map(function(hash) {
|
|
||||||
if (_.isString(hash)) {
|
|
||||||
return BufferUtil.reverse(new Buffer(hash, 'hex'));
|
|
||||||
} else {
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
starts = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < starts.length; i++) {
|
|
||||||
if (starts[i].length !== 32) {
|
|
||||||
throw new Error('Invalid hash ' + i + ' length: ' + starts[i].length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stop = obj.stop;
|
|
||||||
if (_.isString(stop)) {
|
|
||||||
stop = BufferUtil.reverse(new Buffer(stop, 'hex'));
|
|
||||||
}
|
|
||||||
if (!stop) {
|
|
||||||
stop = BufferUtil.NULL_HASH;
|
|
||||||
}
|
|
||||||
obj.starts = starts;
|
|
||||||
obj.stop = stop;
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The version message is used on connection creation to advertise
|
|
||||||
* the type of node. The remote node will respond with its version, and no
|
|
||||||
* communication is possible until both peers have exchanged their versions.
|
|
||||||
* By default, bitcore advertises itself as named `bitcore:0.8`.
|
|
||||||
*
|
|
||||||
* @param{Object} obj - properties for the version
|
|
||||||
* @param{String} obj.subversion - version of the client
|
|
||||||
* @param{Buffer} obj.nonce - a random 8 byte buffer
|
|
||||||
*/
|
|
||||||
commands.version = function(obj) {
|
|
||||||
Message.call(this, obj);
|
|
||||||
this.command = 'version';
|
|
||||||
_.assign(this, obj);
|
|
||||||
this.magicNumber = magicNumber;
|
|
||||||
this.nonce = this.nonce || getNonce();
|
|
||||||
this.services = this.services || new BN(1, 10);
|
|
||||||
this.timestamp = this.timestamp || new Date();
|
|
||||||
this.version = this.version || protocolVersion;
|
|
||||||
this.subversion = this.subversion || '/bitcore:' + packageInfo.version + '/';
|
|
||||||
this.startHeight = this.startHeight || 0;
|
|
||||||
};
|
|
||||||
inherits(commands.version, Message);
|
|
||||||
|
|
||||||
commands.version.fromObject = function(obj) {
|
|
||||||
return new commands.version(obj);
|
|
||||||
};
|
|
||||||
|
|
||||||
commands.version.fromBuffer = function(payload) {
|
|
||||||
var parser = new BufferReader(payload);
|
|
||||||
var obj = {};
|
|
||||||
obj.version = parser.readUInt32LE();
|
|
||||||
obj.services = parser.readUInt64LEBN();
|
|
||||||
obj.timestamp = new Date(parser.readUInt64LEBN().toNumber() * 1000);
|
|
||||||
|
|
||||||
obj.addrMe = {
|
|
||||||
services: parser.readUInt64LEBN(),
|
|
||||||
ip: parseIP(parser),
|
|
||||||
port: parser.readUInt16BE()
|
|
||||||
};
|
|
||||||
obj.addrYou = {
|
|
||||||
services: parser.readUInt64LEBN(),
|
|
||||||
ip: parseIP(parser),
|
|
||||||
port: parser.readUInt16BE()
|
|
||||||
};
|
|
||||||
obj.nonce = parser.read(8);
|
|
||||||
obj.subversion = parser.readVarLengthBuffer().toString();
|
|
||||||
obj.startHeight = parser.readUInt32LE();
|
|
||||||
|
|
||||||
if(parser.finished()) {
|
|
||||||
obj.relay = true;
|
|
||||||
} else {
|
|
||||||
obj.relay = !!parser.readUInt8();
|
|
||||||
}
|
|
||||||
checkFinished(parser);
|
|
||||||
|
|
||||||
return commands.version.fromObject(obj);
|
|
||||||
};
|
|
||||||
|
|
||||||
commands.version.prototype.getPayload = function() {
|
|
||||||
var bw = new BufferWriter();
|
|
||||||
bw.writeUInt32LE(this.version);
|
|
||||||
bw.writeUInt64LEBN(this.services);
|
|
||||||
|
|
||||||
var timestampBuffer = new Buffer(Array(8));
|
|
||||||
timestampBuffer.writeUInt32LE(Math.round(this.timestamp.getTime() / 1000), 0);
|
|
||||||
bw.write(timestampBuffer);
|
|
||||||
|
|
||||||
writeAddr(this.addrMe, bw);
|
|
||||||
writeAddr(this.addrYou, bw);
|
|
||||||
bw.write(this.nonce);
|
|
||||||
bw.writeVarintNum(this.subversion.length);
|
|
||||||
bw.write(new Buffer(this.subversion, 'ascii'));
|
|
||||||
bw.writeUInt32LE(this.startHeight);
|
|
||||||
bw.writeUInt8(this.relay);
|
|
||||||
|
|
||||||
return bw.concat();
|
|
||||||
};
|
|
||||||
|
|
||||||
/* verack */
|
/* verack */
|
||||||
|
|
||||||
@ -263,7 +79,7 @@ function builder(options) {
|
|||||||
Message.call(this, options);
|
Message.call(this, options);
|
||||||
this.command = 'ping';
|
this.command = 'ping';
|
||||||
this.magicNumber = magicNumber;
|
this.magicNumber = magicNumber;
|
||||||
this.nonce = options.nonce || getNonce();
|
this.nonce = options.nonce || utils.getNonce();
|
||||||
};
|
};
|
||||||
inherits(commands.ping, Message);
|
inherits(commands.ping, Message);
|
||||||
|
|
||||||
@ -280,7 +96,7 @@ function builder(options) {
|
|||||||
var parser = new BufferReader(payload);
|
var parser = new BufferReader(payload);
|
||||||
obj.nonce = parser.read(8);
|
obj.nonce = parser.read(8);
|
||||||
|
|
||||||
checkFinished(parser);
|
utils.checkFinished(parser);
|
||||||
return commands.ping.fromObject(obj);
|
return commands.ping.fromObject(obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -303,7 +119,7 @@ function builder(options) {
|
|||||||
var parser = new BufferReader(payload);
|
var parser = new BufferReader(payload);
|
||||||
obj.nonce = parser.read(8);
|
obj.nonce = parser.read(8);
|
||||||
|
|
||||||
checkFinished(parser);
|
utils.checkFinished(parser);
|
||||||
return commands.pong.fromObject(obj);
|
return commands.pong.fromObject(obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -311,28 +127,7 @@ function builder(options) {
|
|||||||
return this.nonce;
|
return this.nonce;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* block */
|
commands.block = require('./commands/block')({Block: Block, magicNumber: magicNumber});
|
||||||
|
|
||||||
commands.block = function(options) {
|
|
||||||
Message.call(this, options);
|
|
||||||
this.command = 'block';
|
|
||||||
this.magicNumber = magicNumber;
|
|
||||||
this.block = options.block;
|
|
||||||
};
|
|
||||||
inherits(commands.block, Message);
|
|
||||||
|
|
||||||
commands.block.fromObject = function(options) {
|
|
||||||
return new commands.block(options);
|
|
||||||
};
|
|
||||||
|
|
||||||
commands.block.fromBuffer = function(payload) {
|
|
||||||
var block = Block.fromBuffer(payload);
|
|
||||||
return commands.block.fromObject({block: block});
|
|
||||||
};
|
|
||||||
|
|
||||||
commands.block.prototype.getPayload = function() {
|
|
||||||
return this.block.toBuffer();
|
|
||||||
};
|
|
||||||
|
|
||||||
/* tx */
|
/* tx */
|
||||||
|
|
||||||
@ -390,13 +185,13 @@ function builder(options) {
|
|||||||
obj.inventory.push({type: type, hash: hash});
|
obj.inventory.push({type: type, hash: hash});
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFinished(parser);
|
utils.checkFinished(parser);
|
||||||
return commands.getdata.fromObject(obj);
|
return commands.getdata.fromObject(obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
commands.getdata.prototype.getPayload = function() {
|
commands.getdata.prototype.getPayload = function() {
|
||||||
var bw = new BufferWriter();
|
var bw = new BufferWriter();
|
||||||
writeInventory(this.inventory, bw);
|
utils.writeInventory(this.inventory, bw);
|
||||||
return bw.concat();
|
return bw.concat();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -433,7 +228,7 @@ function builder(options) {
|
|||||||
$.checkState(txn_count === 0, 'txn_count should always be 0');
|
$.checkState(txn_count === 0, 'txn_count should always be 0');
|
||||||
|
|
||||||
}
|
}
|
||||||
checkFinished(parser);
|
utils.checkFinished(parser);
|
||||||
|
|
||||||
return commands.headers.fromObject(obj);
|
return commands.headers.fromObject(obj);
|
||||||
};
|
};
|
||||||
@ -476,14 +271,14 @@ function builder(options) {
|
|||||||
obj.inventory.push({type: type, hash: hash});
|
obj.inventory.push({type: type, hash: hash});
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFinished(parser);
|
utils.checkFinished(parser);
|
||||||
return commands.notfound.fromObject(obj);
|
return commands.notfound.fromObject(obj);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
commands.notfound.prototype.getPayload = function() {
|
commands.notfound.prototype.getPayload = function() {
|
||||||
var bw = new BufferWriter();
|
var bw = new BufferWriter();
|
||||||
writeInventory(this.inventory, bw);
|
utils.writeInventory(this.inventory, bw);
|
||||||
return bw.concat();
|
return bw.concat();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -504,7 +299,7 @@ function builder(options) {
|
|||||||
|
|
||||||
commands.inv.prototype.getPayload = function() {
|
commands.inv.prototype.getPayload = function() {
|
||||||
var bw = new BufferWriter();
|
var bw = new BufferWriter();
|
||||||
writeInventory(this.inventory, bw);
|
utils.writeInventory(this.inventory, bw);
|
||||||
return bw.concat();
|
return bw.concat();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -521,7 +316,7 @@ function builder(options) {
|
|||||||
obj.inventory.push({type: type, hash: hash});
|
obj.inventory.push({type: type, hash: hash});
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFinished(parser);
|
utils.checkFinished(parser);
|
||||||
return commands.inv.fromObject(obj);
|
return commands.inv.fromObject(obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -550,12 +345,12 @@ function builder(options) {
|
|||||||
// todo: time only available on versions >=31402
|
// todo: time only available on versions >=31402
|
||||||
var time = new Date(parser.readUInt32LE() * 1000);
|
var time = new Date(parser.readUInt32LE() * 1000);
|
||||||
|
|
||||||
var addr = parseAddr(parser);
|
var addr = utils.parseAddr(parser);
|
||||||
addr.time = time;
|
addr.time = time;
|
||||||
obj.addresses.push(addr);
|
obj.addresses.push(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFinished(parser);
|
utils.checkFinished(parser);
|
||||||
return commands.addr.fromObject(obj);
|
return commands.addr.fromObject(obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -566,7 +361,7 @@ function builder(options) {
|
|||||||
for (var i = 0; i < this.addresses.length; i++) {
|
for (var i = 0; i < this.addresses.length; i++) {
|
||||||
var addr = this.addresses[i];
|
var addr = this.addresses[i];
|
||||||
bw.writeUInt32LE(addr.time.getTime() / 1000);
|
bw.writeUInt32LE(addr.time.getTime() / 1000);
|
||||||
writeAddr(addr, bw);
|
utils.writeAddr(addr, bw);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bw.concat();
|
return bw.concat();
|
||||||
@ -594,7 +389,7 @@ function builder(options) {
|
|||||||
var parser = new BufferReader(payload);
|
var parser = new BufferReader(payload);
|
||||||
obj.payload = parser.readVarLengthBuffer();
|
obj.payload = parser.readVarLengthBuffer();
|
||||||
obj.signature = parser.readVarLengthBuffer();
|
obj.signature = parser.readVarLengthBuffer();
|
||||||
checkFinished(parser);
|
utils.checkFinished(parser);
|
||||||
return commands.alert.fromObject(obj);
|
return commands.alert.fromObject(obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -717,7 +512,7 @@ function builder(options) {
|
|||||||
$.checkArgument(payload);
|
$.checkArgument(payload);
|
||||||
var parser = new BufferReader(payload);
|
var parser = new BufferReader(payload);
|
||||||
obj.data = parser.readVarLengthBuffer();
|
obj.data = parser.readVarLengthBuffer();
|
||||||
checkFinished(parser);
|
utils.checkFinished(parser);
|
||||||
return commands.filteradd.fromObject(obj);
|
return commands.filteradd.fromObject(obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -763,7 +558,7 @@ function builder(options) {
|
|||||||
this.version = protocolVersion;
|
this.version = protocolVersion;
|
||||||
this.magicNumber = magicNumber;
|
this.magicNumber = magicNumber;
|
||||||
|
|
||||||
options = sanitizeStartStop(options);
|
options = utils.sanitizeStartStop(options);
|
||||||
this.starts = options.starts;
|
this.starts = options.starts;
|
||||||
this.stop = options.stop;
|
this.stop = options.stop;
|
||||||
|
|
||||||
@ -787,7 +582,7 @@ function builder(options) {
|
|||||||
obj.starts.push(parser.read(32));
|
obj.starts.push(parser.read(32));
|
||||||
}
|
}
|
||||||
obj.stop = parser.read(32);
|
obj.stop = parser.read(32);
|
||||||
checkFinished(parser);
|
utils.checkFinished(parser);
|
||||||
return commands.getblocks.fromObject(obj);
|
return commands.getblocks.fromObject(obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -818,7 +613,7 @@ function builder(options) {
|
|||||||
this.version = protocolVersion;
|
this.version = protocolVersion;
|
||||||
this.magicNumber = magicNumber;
|
this.magicNumber = magicNumber;
|
||||||
|
|
||||||
options = sanitizeStartStop(options);
|
options = utils.sanitizeStartStop(options);
|
||||||
this.starts = options.starts;
|
this.starts = options.starts;
|
||||||
this.stop = options.stop;
|
this.stop = options.stop;
|
||||||
|
|
||||||
@ -842,7 +637,7 @@ function builder(options) {
|
|||||||
obj.starts.push(parser.read(32));
|
obj.starts.push(parser.read(32));
|
||||||
}
|
}
|
||||||
obj.stop = parser.read(32);
|
obj.stop = parser.read(32);
|
||||||
checkFinished(parser);
|
utils.checkFinished(parser);
|
||||||
return commands.getheaders.fromObject(obj);
|
return commands.getheaders.fromObject(obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -881,7 +676,6 @@ function builder(options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* getaddr */
|
/* getaddr */
|
||||||
//todo: need test data
|
|
||||||
commands.getaddr = function(options) {
|
commands.getaddr = function(options) {
|
||||||
Message.call(this, options);
|
Message.call(this, options);
|
||||||
this.magicNumber = magicNumber;
|
this.magicNumber = magicNumber;
|
||||||
|
|||||||
35
lib/messages/commands/block.js
Normal file
35
lib/messages/commands/block.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Message = require('../message');
|
||||||
|
var inherits = require('util').inherits;
|
||||||
|
var bitcore = require('bitcore');
|
||||||
|
|
||||||
|
var Block = bitcore.Block;
|
||||||
|
var magicNumber = bitcore.Networks.defaultNetwork.networkMagic.readUInt32LE(0);
|
||||||
|
|
||||||
|
function BlockMessage(options) {
|
||||||
|
Message.call(this, options);
|
||||||
|
this.command = 'block';
|
||||||
|
this.magicNumber = magicNumber;
|
||||||
|
this.block = options.block;
|
||||||
|
}
|
||||||
|
inherits(BlockMessage, Message);
|
||||||
|
|
||||||
|
BlockMessage.fromObject = function(options) {
|
||||||
|
return new BlockMessage(options);
|
||||||
|
};
|
||||||
|
|
||||||
|
BlockMessage.fromBuffer = function(payload) {
|
||||||
|
var block = Block.fromBuffer(payload);
|
||||||
|
return BlockMessage.fromObject({block: block});
|
||||||
|
};
|
||||||
|
|
||||||
|
BlockMessage.prototype.getPayload = function() {
|
||||||
|
return this.block.toBuffer();
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = function(options) {
|
||||||
|
Block = options.Block;
|
||||||
|
magicNumber = options.magicNumber;
|
||||||
|
return BlockMessage;
|
||||||
|
};
|
||||||
100
lib/messages/commands/version.js
Normal file
100
lib/messages/commands/version.js
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Message = require('../message');
|
||||||
|
var inherits = require('util').inherits;
|
||||||
|
var bitcore = require('bitcore');
|
||||||
|
var BufferWriter = bitcore.encoding.BufferWriter;
|
||||||
|
var BufferReader = bitcore.encoding.BufferReader;
|
||||||
|
var _ = bitcore.deps._;
|
||||||
|
var BN = bitcore.crypto.BN;
|
||||||
|
|
||||||
|
var utils = require('../utils');
|
||||||
|
var magicNumber = bitcore.Networks.defaultNetwork.networkMagic.readUInt32LE(0);
|
||||||
|
var protocolVersion = 70000;
|
||||||
|
var packageInfo = require('../../../package.json');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The version message is used on connection creation to advertise
|
||||||
|
* the type of node. The remote node will respond with its version, and no
|
||||||
|
* communication is possible until both peers have exchanged their versions.
|
||||||
|
* By default, bitcore advertises itself as named `bitcore:0.8`.
|
||||||
|
*
|
||||||
|
* @param{Object} obj - properties for the version
|
||||||
|
* @param{String} obj.subversion - version of the client
|
||||||
|
* @param{Buffer} obj.nonce - a random 8 byte buffer
|
||||||
|
*/
|
||||||
|
function VersionMessage(obj) {
|
||||||
|
/* jshint maxcomplexity: 10 */
|
||||||
|
Message.call(this, obj);
|
||||||
|
this.command = 'version';
|
||||||
|
_.assign(this, obj);
|
||||||
|
this.magicNumber = magicNumber;
|
||||||
|
this.nonce = this.nonce || utils.getNonce();
|
||||||
|
this.services = this.services || new BN(1, 10);
|
||||||
|
this.timestamp = this.timestamp || new Date();
|
||||||
|
this.version = this.version || protocolVersion;
|
||||||
|
this.subversion = this.subversion || '/bitcore:' + packageInfo.version + '/';
|
||||||
|
this.startHeight = this.startHeight || 0;
|
||||||
|
};
|
||||||
|
inherits(VersionMessage, Message);
|
||||||
|
|
||||||
|
VersionMessage.fromObject = function(obj) {
|
||||||
|
return new VersionMessage(obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
VersionMessage.fromBuffer = function(payload) {
|
||||||
|
var parser = new BufferReader(payload);
|
||||||
|
var obj = {};
|
||||||
|
obj.version = parser.readUInt32LE();
|
||||||
|
obj.services = parser.readUInt64LEBN();
|
||||||
|
obj.timestamp = new Date(parser.readUInt64LEBN().toNumber() * 1000);
|
||||||
|
|
||||||
|
obj.addrMe = {
|
||||||
|
services: parser.readUInt64LEBN(),
|
||||||
|
ip: utils.parseIP(parser),
|
||||||
|
port: parser.readUInt16BE()
|
||||||
|
};
|
||||||
|
obj.addrYou = {
|
||||||
|
services: parser.readUInt64LEBN(),
|
||||||
|
ip: utils.parseIP(parser),
|
||||||
|
port: parser.readUInt16BE()
|
||||||
|
};
|
||||||
|
obj.nonce = parser.read(8);
|
||||||
|
obj.subversion = parser.readVarLengthBuffer().toString();
|
||||||
|
obj.startHeight = parser.readUInt32LE();
|
||||||
|
|
||||||
|
if(parser.finished()) {
|
||||||
|
obj.relay = true;
|
||||||
|
} else {
|
||||||
|
obj.relay = !!parser.readUInt8();
|
||||||
|
}
|
||||||
|
utils.checkFinished(parser);
|
||||||
|
|
||||||
|
return VersionMessage.fromObject(obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
VersionMessage.prototype.getPayload = function() {
|
||||||
|
var bw = new BufferWriter();
|
||||||
|
bw.writeUInt32LE(this.version);
|
||||||
|
bw.writeUInt64LEBN(this.services);
|
||||||
|
|
||||||
|
var timestampBuffer = new Buffer(Array(8));
|
||||||
|
timestampBuffer.writeUInt32LE(Math.round(this.timestamp.getTime() / 1000), 0);
|
||||||
|
bw.write(timestampBuffer);
|
||||||
|
|
||||||
|
utils.writeAddr(this.addrMe, bw);
|
||||||
|
utils.writeAddr(this.addrYou, bw);
|
||||||
|
bw.write(this.nonce);
|
||||||
|
bw.writeVarintNum(this.subversion.length);
|
||||||
|
bw.write(new Buffer(this.subversion, 'ascii'));
|
||||||
|
bw.writeUInt32LE(this.startHeight);
|
||||||
|
bw.writeUInt8(this.relay);
|
||||||
|
|
||||||
|
return bw.concat();
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = function(options) {
|
||||||
|
magicNumber = options.magicNumber || magicNumber;
|
||||||
|
protocolVersion = options.protocolVersion || protocolVersion;
|
||||||
|
return VersionMessage;
|
||||||
|
};
|
||||||
109
lib/messages/utils.js
Normal file
109
lib/messages/utils.js
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var bitcore = require('bitcore');
|
||||||
|
var BufferUtil = bitcore.util.buffer;
|
||||||
|
var $ = bitcore.util.preconditions;
|
||||||
|
var _ = bitcore.deps._;
|
||||||
|
var utils;
|
||||||
|
|
||||||
|
module.exports = utils = {
|
||||||
|
checkFinished: function checkFinished(parser) {
|
||||||
|
if(!parser.finished()) {
|
||||||
|
throw new Error('Data still available after parsing');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getNonce: function getNonce() {
|
||||||
|
return bitcore.crypto.Random.getRandomBuffer(8);
|
||||||
|
},
|
||||||
|
writeIP: function writeIP(ip, bw) {
|
||||||
|
var words = ip.v6.split(':').map(function(s) {
|
||||||
|
return new Buffer(s, 'hex');
|
||||||
|
});
|
||||||
|
for (var i = 0; i < words.length; i++) {
|
||||||
|
var word = words[i];
|
||||||
|
bw.write(word);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
writeAddr: function writeAddr(addr, bw) {
|
||||||
|
if (_.isUndefined(addr)) {
|
||||||
|
var pad = new Buffer(Array(26));
|
||||||
|
bw.write(pad);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bw.writeUInt64LEBN(addr.services);
|
||||||
|
utils.writeIP(addr.ip, bw);
|
||||||
|
bw.writeUInt16BE(addr.port);
|
||||||
|
},
|
||||||
|
writeInventory: function writeInventory(inventory, bw) {
|
||||||
|
bw.writeVarintNum(inventory.length);
|
||||||
|
inventory.forEach(function(value) {
|
||||||
|
bw.writeUInt32LE(value.type);
|
||||||
|
bw.write(value.hash);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
parseIP: function parseIP(parser) {
|
||||||
|
var ipv6 = [];
|
||||||
|
var ipv4 = [];
|
||||||
|
for (var a = 0; a < 8; a++) {
|
||||||
|
var word = parser.read(2);
|
||||||
|
ipv6.push(word.toString('hex'));
|
||||||
|
if (a >= 6) {
|
||||||
|
ipv4.push(word[0]);
|
||||||
|
ipv4.push(word[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ipv6 = ipv6.join(':');
|
||||||
|
ipv4 = ipv4.join('.');
|
||||||
|
return {
|
||||||
|
v6: ipv6,
|
||||||
|
v4: ipv4
|
||||||
|
};
|
||||||
|
},
|
||||||
|
parseAddr: function parseAddr(parser) {
|
||||||
|
var services = parser.readUInt64LEBN();
|
||||||
|
var ip = utils.parseIP(parser);
|
||||||
|
var port = parser.readUInt16BE();
|
||||||
|
return {
|
||||||
|
services: services,
|
||||||
|
ip: ip,
|
||||||
|
port: port
|
||||||
|
};
|
||||||
|
},
|
||||||
|
sanitizeStartStop: function sanitizeStartStop(obj) {
|
||||||
|
/* jshint maxcomplexity: 10 */
|
||||||
|
/* jshint maxstatements: 20 */
|
||||||
|
$.checkArgument(_.isUndefined(obj.starts) || _.isArray(obj.starts));
|
||||||
|
var starts = obj.starts;
|
||||||
|
var stop = obj.stop;
|
||||||
|
if (starts) {
|
||||||
|
starts = starts.map(function(hash) {
|
||||||
|
if (_.isString(hash)) {
|
||||||
|
return BufferUtil.reverse(new Buffer(hash, 'hex'));
|
||||||
|
} else {
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
starts = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < starts.length; i++) {
|
||||||
|
if (starts[i].length !== 32) {
|
||||||
|
throw new Error('Invalid hash ' + i + ' length: ' + starts[i].length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stop = obj.stop;
|
||||||
|
if (_.isString(stop)) {
|
||||||
|
stop = BufferUtil.reverse(new Buffer(stop, 'hex'));
|
||||||
|
}
|
||||||
|
if (!stop) {
|
||||||
|
stop = BufferUtil.NULL_HASH;
|
||||||
|
}
|
||||||
|
obj.starts = starts;
|
||||||
|
obj.stop = stop;
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user