refactor network handling

This commit is contained in:
Manuel Araoz 2015-04-20 15:44:09 -03:00
parent 8313c4df5b
commit f01d6c98fb
31 changed files with 75 additions and 83 deletions

View File

@ -36,10 +36,10 @@ For advanced usage, you can also customize which constructor is used for Block a
var messages = new Messages({Block: MyBlock, Transaction: MyTransaction}); var messages = new Messages({Block: MyBlock, Transaction: MyTransaction});
``` ```
And additionally custom network magic: And additionally custom network:
```javascript ```javascript
var messages = new Messages({magicNumber: 0x0b120907}); var messages = new Messages({network: Networks.testnet});
``` ```
## List of Messages ## List of Messages

View File

@ -22,7 +22,7 @@ var Block = bitcore.Block;
var Transaction = bitcore.Transaction; var Transaction = bitcore.Transaction;
// config // config
var network = Networks.livenet; var network = process.env.NETWORK === 'testnet'? Networks.testnet: Networks.livenet;
var blockHash = { var blockHash = {
'livenet': '000000000000000013413cf2536b491bf0988f52e90c476ffeb701c8bfdb1db9', 'livenet': '000000000000000013413cf2536b491bf0988f52e90c476ffeb701c8bfdb1db9',
'testnet': '0000000058cc069d964711cd25083c0a709f4df2b34c8ff9302ce71fe5b45786' 'testnet': '0000000058cc069d964711cd25083c0a709f4df2b34c8ff9302ce71fe5b45786'
@ -40,8 +40,12 @@ var txHash = {
describe('Integration with ' + network.name + ' bitcoind', function() { describe('Integration with ' + network.name + ' bitcoind', function() {
this.timeout(15000); this.timeout(15000);
var opts = {
host: 'localhost',
network: network.name
};
it('handshakes', function(cb) { it('handshakes', function(cb) {
var peer = new Peer('localhost', network); var peer = new Peer(opts);
peer.once('version', function(m) { peer.once('version', function(m) {
m.version.should.be.above(70000); m.version.should.be.above(70000);
m.services.toString().should.equal('1'); m.services.toString().should.equal('1');
@ -57,7 +61,7 @@ describe('Integration with ' + network.name + ' bitcoind', function() {
peer.connect(); peer.connect();
}); });
var connect = function(cb) { var connect = function(cb) {
var peer = new Peer('localhost', network); var peer = new Peer(opts);
peer.once('ready', function() { peer.once('ready', function() {
cb(peer); cb(peer);
}); });
@ -164,20 +168,28 @@ describe('Integration with ' + network.name + ' bitcoind', function() {
message.headers.length.should.equal(3); message.headers.length.should.equal(3);
cb(); cb();
}); });
var message = messages.GetHeaders({starts: from, stop: stop}); var message = messages.GetHeaders({
starts: from,
stop: stop
});
peer.sendMessage(message); peer.sendMessage(message);
}); });
}); });
it('gets blocks', function(cb) { it.only('gets blocks', function(cb) {
connect(function(peer) { connect(function(peer) {
peer.once('inv', function(message) { peer.once('inv', function(message) {
message.command.should.equal('inv'); message.command.should.equal('inv');
console.log('LLEGO UN INV', message.inventory.length);
if (message.inventory.length === 2) { if (message.inventory.length === 2) {
message.inventory[0].type.should.equal(Inventory.TYPE.BLOCK); message.inventory[0].type.should.equal(Inventory.TYPE.BLOCK);
message.inventory[1].type.should.equal(Inventory.TYPE.BLOCK);
cb(); cb();
} }
}); });
var message = messages.GetBlocks({starts: from, stop: stop}); var message = messages.GetBlocks({
starts: from,
stop: stop
});
peer.sendMessage(message); peer.sendMessage(message);
}); });
}); });

View File

@ -11,8 +11,8 @@ function builder(options) {
options = {}; options = {};
} }
if (!options.magicNumber) { if (!options.network) {
options.magicNumber = bitcore.Networks.defaultNetwork.networkMagic.readUInt32LE(0); options.network = bitcore.Networks.defaultNetwork;
} }
options.Block = options.Block || bitcore.Block; options.Block = options.Block || bitcore.Block;
@ -30,7 +30,7 @@ function builder(options) {
}, },
defaults: { defaults: {
protocolVersion: options.protocolVersion, protocolVersion: options.protocolVersion,
magicNumber: options.magicNumber network: options.network
}, },
inventoryCommands: [ inventoryCommands: [
'getdata', 'getdata',

View File

@ -12,14 +12,12 @@ var BufferWriter = bitcore.encoding.BufferWriter;
/** /**
* @param {Array=} arg - An array of addrs * @param {Array=} arg - An array of addrs
* @param {Object=} options * @param {Object=} options
* @param {Number} options.magicNumber
* @extends Message * @extends Message
* @constructor * @constructor
*/ */
function AddrMessage(arg, options) { function AddrMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.command = 'addr'; this.command = 'addr';
this.magicNumber = options.magicNumber;
$.checkArgument( $.checkArgument(
_.isUndefined(arg) || _.isUndefined(arg) ||
(Array.isArray(arg) && (Array.isArray(arg) &&

View File

@ -12,13 +12,11 @@ var BufferWriter = bitcore.encoding.BufferWriter;
* @param {Buffer=} arg.payload * @param {Buffer=} arg.payload
* @param {Buffer=} arg.signature * @param {Buffer=} arg.signature
* @param {Object} options * @param {Object} options
* @param {Number} options.magicNumber
* @extends Message * @extends Message
* @constructor * @constructor
*/ */
function AlertMessage(arg, options) { function AlertMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.magicNumber = options.magicNumber;
this.command = 'alert'; this.command = 'alert';
if (!arg) { if (!arg) {
arg = {}; arg = {};

View File

@ -9,7 +9,6 @@ var _ = bitcore.deps._;
/** /**
* @param {Block=} arg - An instance of a Block * @param {Block=} arg - An instance of a Block
* @param {Object} options * @param {Object} options
* @param {Number} options.magicNumber
* @param {Function} options.Block - A block constructor * @param {Function} options.Block - A block constructor
* @extends Message * @extends Message
* @constructor * @constructor
@ -18,7 +17,6 @@ function BlockMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.Block = options.Block; this.Block = options.Block;
this.command = 'block'; this.command = 'block';
this.magicNumber = options.magicNumber;
$.checkArgument( $.checkArgument(
_.isUndefined(arg) || arg instanceof this.Block, _.isUndefined(arg) || arg instanceof this.Block,
'An instance of Block or undefined is expected' 'An instance of Block or undefined is expected'

View File

@ -14,13 +14,11 @@ var _ = bitcore.deps._;
* Request peer to add data to a bloom filter already set by 'filterload' * Request peer to add data to a bloom filter already set by 'filterload'
* @param {Buffer=} data - Array of bytes representing bloom filter data * @param {Buffer=} data - Array of bytes representing bloom filter data
* @param {Object=} options * @param {Object=} options
* @param {Number} options.magicNumber
* @extends Message * @extends Message
* @constructor * @constructor
*/ */
function FilteraddMessage(arg, options) { function FilteraddMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.magicNumber = options.magicNumber;
this.command = 'filteradd'; this.command = 'filteradd';
$.checkArgument( $.checkArgument(
_.isUndefined(arg) || BufferUtil.isBuffer(arg), _.isUndefined(arg) || BufferUtil.isBuffer(arg),

View File

@ -8,12 +8,10 @@ var BufferUtil = bitcore.util.buffer;
/** /**
* Request peer to clear data for a bloom filter * Request peer to clear data for a bloom filter
* @extends Message * @extends Message
* @param {Number} options.magicNumber
* @constructor * @constructor
*/ */
function FilterclearMessage(arg, options) { function FilterclearMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.magicNumber = options.magicNumber;
this.command = 'filterclear'; this.command = 'filterclear';
} }
inherits(FilterclearMessage, Message); inherits(FilterclearMessage, Message);

View File

@ -12,13 +12,11 @@ var _ = bitcore.deps._;
* Request peer to send inv messages based on a bloom filter * Request peer to send inv messages based on a bloom filter
* @param {BloomFilter=} arg - An instance of BloomFilter * @param {BloomFilter=} arg - An instance of BloomFilter
* @param {Object} options * @param {Object} options
* @param {Number} options.magicNumber
* @extends Message * @extends Message
* @constructor * @constructor
*/ */
function FilterloadMessage(arg, options) { function FilterloadMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.magicNumber = options.magicNumber;
this.command = 'filterload'; this.command = 'filterload';
$.checkArgument( $.checkArgument(
_.isUndefined(arg) || arg instanceof BloomFilter, _.isUndefined(arg) || arg instanceof BloomFilter,

View File

@ -9,12 +9,10 @@ var BufferUtil = bitcore.util.buffer;
* Request information about active peers * Request information about active peers
* @extends Message * @extends Message
* @param {Object} options * @param {Object} options
* @param {Number} options.magicNumber
* @constructor * @constructor
*/ */
function GetaddrMessage(arg, options) { function GetaddrMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.magicNumber = options.magicNumber;
this.command = 'getaddr'; this.command = 'getaddr';
} }
inherits(GetaddrMessage, Message); inherits(GetaddrMessage, Message);

View File

@ -16,7 +16,6 @@ var $ = bitcore.util.preconditions;
* @param {Array=} arg.starts - Array of buffers or strings with the starting block hashes * @param {Array=} arg.starts - Array of buffers or strings with the starting block hashes
* @param {Buffer=} arg.stop - Hash of the last block * @param {Buffer=} arg.stop - Hash of the last block
* @param {Object} options * @param {Object} options
* @param {Number} options.magicNumber
* @extends Message * @extends Message
* @constructor * @constructor
*/ */
@ -24,7 +23,6 @@ function GetblocksMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.command = 'getblocks'; this.command = 'getblocks';
this.version = options.protocolVersion; this.version = options.protocolVersion;
this.magicNumber = options.magicNumber;
if (!arg) { if (!arg) {
arg = {}; arg = {};
} }

View File

@ -11,14 +11,12 @@ var _ = bitcore.deps._;
/** /**
* @param {Object|Array=} - options - If options is an array will use as "inventory" * @param {Object|Array=} - options - If options is an array will use as "inventory"
* @param {Array=} options.inventory - An array of inventory items * @param {Array=} options.inventory - An array of inventory items
* @param {Number} options.magicNumber
* @extends Message * @extends Message
* @constructor * @constructor
*/ */
function GetdataMessage(arg, options) { function GetdataMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.command = 'getdata'; this.command = 'getdata';
this.magicNumber = options.magicNumber;
utils.checkInventory(arg); utils.checkInventory(arg);
this.inventory = arg; this.inventory = arg;
} }

View File

@ -15,7 +15,6 @@ var $ = bitcore.util.preconditions;
* @param {Object=} options * @param {Object=} options
* @param {Array=} options.starts - Array of buffers or strings with the starting block hashes * @param {Array=} options.starts - Array of buffers or strings with the starting block hashes
* @param {Buffer=} options.stop - Hash of the last block * @param {Buffer=} options.stop - Hash of the last block
* @param {Number} options.magicNumber
* @extends Message * @extends Message
* @constructor * @constructor
*/ */
@ -23,7 +22,6 @@ function GetheadersMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.command = 'getheaders'; this.command = 'getheaders';
this.version = options.protocolVersion; this.version = options.protocolVersion;
this.magicNumber = options.magicNumber;
if (!arg) { if (!arg) {
arg = {}; arg = {};
} }

View File

@ -15,7 +15,6 @@ var $ = bitcore.util.preconditions;
* @param {Array} arg - An array of BlockHeader instances * @param {Array} arg - An array of BlockHeader instances
* @param {Object=} options * @param {Object=} options
* @param {Array=} options.headers - array of block headers * @param {Array=} options.headers - array of block headers
* @param {Number} options.magicNumber
* @param {Function} options.BlockHeader - a BlockHeader constructor * @param {Function} options.BlockHeader - a BlockHeader constructor
* @extends Message * @extends Message
* @constructor * @constructor
@ -23,7 +22,6 @@ var $ = bitcore.util.preconditions;
function HeadersMessage(arg, options) { function HeadersMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.BlockHeader = options.BlockHeader; this.BlockHeader = options.BlockHeader;
this.magicNumber = options.magicNumber;
this.command = 'headers'; this.command = 'headers';
$.checkArgument( $.checkArgument(
_.isUndefined(arg) || (Array.isArray(arg) && arg[0] instanceof this.BlockHeader), _.isUndefined(arg) || (Array.isArray(arg) && arg[0] instanceof this.BlockHeader),

View File

@ -12,14 +12,12 @@ var _ = bitcore.deps._;
* @param {Array=} arg - An array of inventory * @param {Array=} arg - An array of inventory
* @param {Object} options * @param {Object} options
* @param {Array=} options.inventory - An array of inventory items * @param {Array=} options.inventory - An array of inventory items
* @param {Number} options.magicNumber
* @extends Message * @extends Message
* @constructor * @constructor
*/ */
function InvMessage(arg, options) { function InvMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.command = 'inv'; this.command = 'inv';
this.magicNumber = options.magicNumber;
utils.checkInventory(arg); utils.checkInventory(arg);
this.inventory = arg; this.inventory = arg;
} }

View File

@ -10,13 +10,11 @@ var BufferUtil = bitcore.util.buffer;
* transactions it has verified but which have not yet confirmed. * transactions it has verified but which have not yet confirmed.
* @see https://en.bitcoin.it/wiki/Protocol_documentation#mempool * @see https://en.bitcoin.it/wiki/Protocol_documentation#mempool
* @param {Object} options * @param {Object} options
* @param {Number} options.magicNumber
* @extends Message * @extends Message
* @constructor * @constructor
*/ */
function MempoolMessage(arg, options) { function MempoolMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.magicNumber = options.magicNumber;
this.command = 'mempool'; this.command = 'mempool';
} }
inherits(MempoolMessage, Message); inherits(MempoolMessage, Message);

View File

@ -12,7 +12,6 @@ var _ = bitcore.deps._;
* @see https://en.bitcoin.it/wiki/Protocol_documentation * @see https://en.bitcoin.it/wiki/Protocol_documentation
* @param {MerkleBlock} arg - An instance of MerkleBlock * @param {MerkleBlock} arg - An instance of MerkleBlock
* @param {Object=} options * @param {Object=} options
* @param {Number} options.magicNumber
* @param {Function} options.MerkleBlock - a MerkleBlock constructor * @param {Function} options.MerkleBlock - a MerkleBlock constructor
* @extends Message * @extends Message
* @constructor * @constructor
@ -20,7 +19,6 @@ var _ = bitcore.deps._;
function MerkleblockMessage(arg, options) { function MerkleblockMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.MerkleBlock = options.MerkleBlock; // constructor this.MerkleBlock = options.MerkleBlock; // constructor
this.magicNumber = options.magicNumber;
this.command = 'merkleblock'; this.command = 'merkleblock';
$.checkArgument( $.checkArgument(
_.isUndefined(arg) || arg instanceof this.MerkleBlock, _.isUndefined(arg) || arg instanceof this.MerkleBlock,

View File

@ -12,14 +12,12 @@ var _ = bitcore.deps._;
* @param {Array} arg - An array of inventory * @param {Array} arg - An array of inventory
* @param {Object} options * @param {Object} options
* @param {Array=} options.inventory - An array of inventory items * @param {Array=} options.inventory - An array of inventory items
* @param {Number} options.magicNumber
* @extends Message * @extends Message
* @constructor * @constructor
*/ */
function NotfoundMessage(arg, options) { function NotfoundMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.command = 'notfound'; this.command = 'notfound';
this.magicNumber = options.magicNumber;
utils.checkInventory(arg); utils.checkInventory(arg);
this.inventory = arg; this.inventory = arg;
} }

View File

@ -13,14 +13,12 @@ var BufferReader = bitcore.encoding.BufferReader;
* A message to confirm that a connection is still valid. * A message to confirm that a connection is still valid.
* @param {Number} arg - A nonce for the Ping message * @param {Number} arg - A nonce for the Ping message
* @param {Object=} options * @param {Object=} options
* @param {Number} options.magicNumber
* @extends Message * @extends Message
* @constructor * @constructor
*/ */
function PingMessage(arg, options) { function PingMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.command = 'ping'; this.command = 'ping';
this.magicNumber = options.magicNumber;
$.checkArgument( $.checkArgument(
_.isUndefined(arg) || (BufferUtil.isBuffer(arg) && arg.length === 8), _.isUndefined(arg) || (BufferUtil.isBuffer(arg) && arg.length === 8),
'First argument is expected to be an 8 byte buffer' 'First argument is expected to be an 8 byte buffer'

View File

@ -13,14 +13,12 @@ var BufferReader = bitcore.encoding.BufferReader;
* A message in response to a ping message. * A message in response to a ping message.
* @param {Number} arg - A nonce for the Pong message * @param {Number} arg - A nonce for the Pong message
* @param {Object=} options * @param {Object=} options
* @param {Number} options.magicNumber
* @extends Message * @extends Message
* @constructor * @constructor
*/ */
function PongMessage(arg, options) { function PongMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.command = 'pong'; this.command = 'pong';
this.magicNumber = options.magicNumber;
$.checkArgument( $.checkArgument(
_.isUndefined(arg) || (BufferUtil.isBuffer(arg) && arg.length === 8), _.isUndefined(arg) || (BufferUtil.isBuffer(arg) && arg.length === 8),
'First argument is expected to be an 8 byte buffer' 'First argument is expected to be an 8 byte buffer'

View File

@ -8,7 +8,6 @@ var BufferUtil = bitcore.util.buffer;
// todo: add payload: https://en.bitcoin.it/wiki/Protocol_documentation#reject // todo: add payload: https://en.bitcoin.it/wiki/Protocol_documentation#reject
function RejectMessage(arg, options) { function RejectMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.magicNumber = options.magicNumber;
this.command = 'reject'; this.command = 'reject';
} }
inherits(RejectMessage, Message); inherits(RejectMessage, Message);

View File

@ -9,14 +9,12 @@ var _ = bitcore.deps._;
/** /**
* @param {Transaction=} arg - An instance of Transaction * @param {Transaction=} arg - An instance of Transaction
* @param {Object} options * @param {Object} options
* @param {Number} options.magicNumber
* @extends Message * @extends Message
* @constructor * @constructor
*/ */
function TransactionMessage(arg, options) { function TransactionMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.command = 'tx'; this.command = 'tx';
this.magicNumber = options.magicNumber;
this.Transaction = options.Transaction; this.Transaction = options.Transaction;
$.checkArgument( $.checkArgument(
_.isUndefined(arg) || arg instanceof this.Transaction, _.isUndefined(arg) || arg instanceof this.Transaction,

View File

@ -7,13 +7,11 @@ var BufferUtil = bitcore.util.buffer;
/** /**
* A message in response to a version message. * A message in response to a version message.
* @param {Number} options.magicNumber
* @extends Message * @extends Message
* @constructor * @constructor
*/ */
function VerackMessage(arg, options) { function VerackMessage(arg, options) {
Message.call(this, options); Message.call(this, options);
this.magicNumber = options.magicNumber;
this.command = 'verack'; this.command = 'verack';
} }
inherits(VerackMessage, Message); inherits(VerackMessage, Message);

View File

@ -23,7 +23,6 @@ var packageInfo = require('../../../package.json');
* @param {Date=} arg.timestamp * @param {Date=} arg.timestamp
* @param {Number=} arg.startHeight * @param {Number=} arg.startHeight
* @param {Object} options * @param {Object} options
* @param {Number} options.magicNumber
* @extends Message * @extends Message
* @constructor * @constructor
*/ */
@ -34,7 +33,6 @@ function VersionMessage(arg, options) {
} }
Message.call(this, options); Message.call(this, options);
this.command = 'version'; this.command = 'version';
this.magicNumber = options.magicNumber;
this.version = arg.version || options.protocolVersion; this.version = arg.version || options.protocolVersion;
this.nonce = arg.nonce || utils.getNonce(); this.nonce = arg.nonce || utils.getNonce();
this.services = arg.services || new BN(1, 10); this.services = arg.services || new BN(1, 10);

View File

@ -3,11 +3,12 @@
var bitcore = require('bitcore'); var bitcore = require('bitcore');
var BufferUtil = bitcore.util.buffer; var BufferUtil = bitcore.util.buffer;
var Hash = bitcore.crypto.Hash; var Hash = bitcore.crypto.Hash;
var $ = bitcore.util.preconditions;
/** /**
* A factory to build Bitcoin protocol messages. * A factory to build Bitcoin protocol messages.
* @param {Object=} options * @param {Object=} options
* @param {Number=} options.magicNumber * @param {Network=} options.network
* @param {Function=} options.Block - A block constructor * @param {Function=} options.Block - A block constructor
* @param {Function=} options.BlockHeader - A block header constructor * @param {Function=} options.BlockHeader - A block header constructor
* @param {Function=} options.MerkleBlock - A merkle block constructor * @param {Function=} options.MerkleBlock - A merkle block constructor
@ -26,8 +27,7 @@ function Messages(options) {
if (!options) { if (!options) {
options = {}; options = {};
} }
var defaultMagicNumber = bitcore.Networks.defaultNetwork.networkMagic.readUInt32LE(0); this.network = options.network || bitcore.Networks.defaultNetwork;
this.magicNumber = options.magicNumber || defaultMagicNumber;
} }
Messages.MINIMUM_LENGTH = 20; Messages.MINIMUM_LENGTH = 20;
@ -75,11 +75,13 @@ Messages.prototype.parseBuffer = function(dataBuffer) {
}; };
Messages.prototype._discardUntilNextMessage = function(dataBuffer) { Messages.prototype._discardUntilNextMessage = function(dataBuffer) {
$.checkArgument(dataBuffer);
$.checkState(this.network, 'network must be set');
var i = 0; var i = 0;
for (;;) { for (;;) {
// check if it's the beginning of a new message // check if it's the beginning of a new message
var packageNumber = dataBuffer.slice(0, 4).readUInt32LE(0); var packageNumber = dataBuffer.slice(0, 4).toString('hex');
if (packageNumber === this.magicNumber) { if (packageNumber === this.network.networkMagic.toString('hex')) {
dataBuffer.skip(i); dataBuffer.skip(i);
return true; return true;
} }

View File

@ -1,6 +1,8 @@
'use strict'; 'use strict';
var bitcore = require('bitcore'); var bitcore = require('bitcore');
var $ = bitcore.util.preconditions;
var Networks = bitcore.Networks;
var BufferWriter = bitcore.encoding.BufferWriter; var BufferWriter = bitcore.encoding.BufferWriter;
var Hash = bitcore.crypto.Hash; var Hash = bitcore.crypto.Hash;
@ -9,12 +11,12 @@ var Hash = bitcore.crypto.Hash;
* `getPayload` method to modify the message payload. * `getPayload` method to modify the message payload.
* @param {Object=} options * @param {Object=} options
* @param {String=} options.command * @param {String=} options.command
* @param {Number=} options.magicNumber * @param {Network=} options.network
* @constructor * @constructor
*/ */
function Message(options) { function Message(options) {
this.command = options.command; this.command = options.command;
this.magicNumber = options.magicNumber; this.network = options.network || Networks.defaultNetwork;
} }
/** /**
@ -22,7 +24,7 @@ function Message(options) {
* @constructor * @constructor
*/ */
Message.prototype.toBuffer = Message.prototype.serialize = function() { Message.prototype.toBuffer = Message.prototype.serialize = function() {
$.checkState(this.network, 'Need to have a defined network to serialize message');
var commandBuf = new Buffer(Array(12)); var commandBuf = new Buffer(Array(12));
commandBuf.write(this.command, 'ascii'); commandBuf.write(this.command, 'ascii');
@ -30,7 +32,7 @@ Message.prototype.toBuffer = Message.prototype.serialize = function() {
var checksum = Hash.sha256sha256(payload).slice(0, 4); var checksum = Hash.sha256sha256(payload).slice(0, 4);
var bw = new BufferWriter(); var bw = new BufferWriter();
bw.writeUInt32LE(this.magicNumber); bw.write(this.network.networkMagic);
bw.write(commandBuf); bw.write(commandBuf);
bw.writeUInt32LE(payload.length); bw.writeUInt32LE(payload.length);
bw.write(checksum); bw.write(checksum);

View File

@ -64,7 +64,7 @@ function Peer(options) {
} }
this.messages = options.messages || new Messages({ this.messages = options.messages || new Messages({
magicNumber: this.network.networkMagic.readUInt32LE(0), network: this.network,
Block: bitcore.Block, Block: bitcore.Block,
Transaction: bitcore.Transaction Transaction: bitcore.Transaction
}); });
@ -191,6 +191,7 @@ Peer.prototype.disconnect = function() {
* @param {Message} message - A message instance * @param {Message} message - A message instance
*/ */
Peer.prototype.sendMessage = function(message) { Peer.prototype.sendMessage = function(message) {
console.log('>sending', message.command);
this.socket.write(message.toBuffer()); this.socket.write(message.toBuffer());
}; };
@ -218,6 +219,7 @@ Peer.prototype._sendPong = function(nonce) {
Peer.prototype._readMessage = function() { Peer.prototype._readMessage = function() {
var message = this.messages.parseBuffer(this.dataBuffer); var message = this.messages.parseBuffer(this.dataBuffer);
if (message) { if (message) {
console.log('<read', message.command);
this.emit(message.command, message); this.emit(message.command, message);
this._readMessage(); this._readMessage();
} }

View File

@ -18,7 +18,7 @@ describe('Messages Builder', function() {
it('should return commands with customizations', function() { it('should return commands with customizations', function() {
// instantiate // instantiate
var b = builder({ var b = builder({
magicNumber: 0xd9b4bef9, network: bitcore.Networks.testnet,
Block: bitcore.Block, Block: bitcore.Block,
Transaction: bitcore.Transaction Transaction: bitcore.Transaction
}); });

View File

@ -8,7 +8,7 @@ var P2P = require('../../');
var Messages = P2P.Messages; var Messages = P2P.Messages;
var messages = new Messages(); var messages = new Messages();
var bitcore = require('bitcore'); var bitcore = require('bitcore');
var Data = require('../data/messages');//todo merge with commandData var Data = require('../data/messages'); //todo merge with commandData
var commandData = require('../data/messages.json'); var commandData = require('../data/messages.json');
function getPayloadBuffer(messageBuffer) { function getPayloadBuffer(messageBuffer) {
@ -25,9 +25,9 @@ describe('Messages', function() {
describe('@constructor', function() { describe('@constructor', function() {
it('sets properties correctly', function() { it('sets properties correctly', function() {
var magicNumber = bitcore.Networks.defaultNetwork.networkMagic.readUInt32LE(0); var network = bitcore.Networks.defaultNetwork;
var messages = new Messages({ var messages = new Messages({
magicNumber: magicNumber, network: network,
Block: bitcore.Block, Block: bitcore.Block,
Transaction: bitcore.Transaction Transaction: bitcore.Transaction
}); });
@ -35,17 +35,21 @@ describe('Messages', function() {
should.exist(messages.builder.constructors); should.exist(messages.builder.constructors);
messages.builder.constructors.Block.should.equal(bitcore.Block); messages.builder.constructors.Block.should.equal(bitcore.Block);
messages.builder.constructors.Transaction.should.equal(bitcore.Transaction); messages.builder.constructors.Transaction.should.equal(bitcore.Transaction);
messages.magicNumber.should.equal(magicNumber); messages.network.should.deep.equal(network);
}); });
it('magicNumber should be unique for each set of messages', function() { it('network should be unique for each set of messages', function() {
var messages = new Messages({magicNumber: 123456}); var messages = new Messages({
var messages2 = new Messages({magicNumber: 987654}); network: bitcore.Networks.livenet
messages.magicNumber.should.equal(123456); });
messages2.magicNumber.should.equal(987654); var messages2 = new Messages({
network: bitcore.Networks.testnet
});
messages.network.should.deep.equal(bitcore.Networks.livenet);
messages2.network.should.deep.equal(bitcore.Networks.testnet);
var message1 = messages.Version(); var message1 = messages.Version();
message1.magicNumber.should.equal(123456); message1.network.should.deep.equal(bitcore.Networks.livenet);
var message2 = messages2.Version(); var message2 = messages2.Version();
message2.magicNumber.should.equal(987654); message2.network.should.deep.equal(bitcore.Networks.testnet);
}); });
}); });
@ -81,14 +85,13 @@ describe('Messages', function() {
}); });
}); });
describe('Default Magic Number', function() { describe('Default Network', function() {
var messages = new Messages(); var messages = new Messages();
Object.keys(messages.builder.commandsMap).forEach(function(command) { Object.keys(messages.builder.commandsMap).forEach(function(command) {
var name = messages.builder.commandsMap[command]; var name = messages.builder.commandsMap[command];
it(name, function() { it(name, function() {
var message = messages[name](); var message = messages[name]();
var defaultMagic = bitcore.Networks.defaultNetwork.networkMagic.readUInt32LE(0); message.network.should.deep.equal(bitcore.Networks.defaultNetwork);
message.magicNumber.should.equal(defaultMagic);
}); });
}); });
@ -103,8 +106,10 @@ describe('Messages', function() {
}); });
it('#relay setting works', function() { it('#relay setting works', function() {
[true,false].forEach(function(relay) { [true, false].forEach(function(relay) {
var message = messages.Version({relay: relay}); var message = messages.Version({
relay: relay
});
message.relay.should.equal(relay); message.relay.should.equal(relay);
var messageBuf = message.getPayload(); var messageBuf = message.getPayload();
var newMessage = messages.Version.fromBuffer(messageBuf); var newMessage = messages.Version.fromBuffer(messageBuf);
@ -162,7 +167,8 @@ describe('Messages', function() {
'0102000000ec3995c1bf7269ff728818a65e53af00cbbee6b6eca8ac9ce7bc79d87' + '0102000000ec3995c1bf7269ff728818a65e53af00cbbee6b6eca8ac9ce7bc79d87' +
'7041ed8'; '7041ed8';
var fails = function() { var fails = function() {
messages.parseBuffer(buildMessage(invalidCommand)); var bufs = buildMessage(invalidCommand);
messages.parseBuffer(bufs);
}; };
fails.should.throw('Unsupported message command: malicious'); fails.should.throw('Unsupported message command: malicious');
}); });

View File

@ -8,15 +8,23 @@ describe('Message', function() {
describe('@constructor', function() { describe('@constructor', function() {
it('construct with magic number and command', function() { it('construct with magic number and command', function() {
var message = new Message({magicNumber: 0xd9b4bef9, command: 'command'}); var message = new Message({
network: {
networkMagic: 0xd9b4bef9
},
command: 'command'
});
should.exist(message);
message.command.should.equal('command'); message.command.should.equal('command');
message.magicNumber.should.equal(0xd9b4bef9); message.network.networkMagic.should.equal(0xd9b4bef9);
}); });
}); });
describe('#toBuffer', function() { describe('#toBuffer', function() {
it('serialize to a buffer', function() { it('serialize to a buffer', function() {
var message = new Message({magicNumber: 0xd9b4bef9, command: 'command'}); var message = new Message({
command: 'command'
});
message.getPayload = function() { message.getPayload = function() {
return new Buffer(0); return new Buffer(0);
}; };

1
test/mocha.opts Normal file
View File

@ -0,0 +1 @@
--recursive