diff --git a/lib/messages.js b/lib/messages.js index fe1ff85..74917d9 100644 --- a/lib/messages.js +++ b/lib/messages.js @@ -14,6 +14,7 @@ var _ = bitcore.deps._; var BlockHeaderModel = bitcore.BlockHeader; var BlockModel = bitcore.Block; +var MerkleBlockModel = bitcore.MerkleBlock; var BufferReader = bitcore.encoding.BufferReader; var BufferWriter = bitcore.encoding.BufferWriter; var BufferUtil = bitcore.util.buffer; @@ -315,7 +316,7 @@ function Inventory(inventory) { } util.inherits(Inventory, Message); -// https://en.bitcoin.it/wiki/Protocol_specification#Inventory_Vectors +// https://en.bitcoin.it/wiki/Protocol_specification#Inventory_Vectors Inventory.TYPE = {}; Inventory.TYPE.ERROR = 0; Inventory.TYPE.TX = 1; @@ -720,6 +721,37 @@ Block.prototype.getPayload = function() { module.exports.Block = Message.COMMANDS.block = Block; +/** + * Contains information about a MerkleBlock + * + * @name P2P.Message.MerkleBlock + * @param {MerkleBlock} block + */ +function MerkleBlock(block) { + $.checkArgument(_.isUndefined(block) || block instanceof MerkleBlockModel); + this.command = 'merkleblock'; + + /** + * @type {Block} + * @desc The block received + */ + this.merkleBlock = block; +} +util.inherits(MerkleBlock, Message); + +MerkleBlock.prototype.fromBuffer = function(payload) { + $.checkArgument(BufferUtil.isBuffer(payload)); + var block = MerkleBlockModel(payload); + return new MerkleBlock(block); +}; + +MerkleBlock.prototype.getPayload = function() { + return this.merkleBlock ? this.merkleBlock.toBuffer() : new Buffer(0); +}; + +module.exports.MerkleBlock = Message.COMMANDS.merkleblock = MerkleBlock; + + /** * Contains information about a transaction * @@ -941,5 +973,7 @@ Buffers.prototype.skip = function(i) { [Inventory, GetData, NotFound].forEach(function(clazz) { clazz.forBlock = creatorForItem(clazz, Inventory.TYPE.BLOCK); + clazz.forFilteredBlock = clazz.forMerkleBlock = + creatorForItem(clazz, Inventory.TYPE.FILTERED_BLOCK); clazz.forTransaction = creatorForItem(clazz, Inventory.TYPE.TX); }); diff --git a/lib/pool.js b/lib/pool.js index 98f20ee..47d6596 100644 --- a/lib/pool.js +++ b/lib/pool.js @@ -105,7 +105,7 @@ util.inherits(Pool, EventEmitter); Pool.MaxConnectedPeers = 8; Pool.RetrySeconds = 30; Pool.PeerEvents = ['version', 'inv', 'getdata', 'ping', 'pong', 'addr', - 'getaddr', 'verack', 'reject', 'alert', 'headers', 'block', + 'getaddr', 'verack', 'reject', 'alert', 'headers', 'block', 'merkleblock', 'tx', 'getblocks', 'getheaders', 'error', 'filterload', 'filteradd', 'filterclear' ]; diff --git a/test/data/messages.json b/test/data/messages.json index 551b578..8cd3f61 100644 --- a/test/data/messages.json +++ b/test/data/messages.json @@ -77,5 +77,9 @@ "FILTERCLEAR": { "message": "f9beb4d966696c7465726c6365617200000000005df6e0e2", "payload": "" + }, + "MERKLEBLOCK": { + "message": "f9beb4d96d65726b6c65626c6f636b00d7000000365913480100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc880670100000000007f16c5962e8bd963659c793ce370d95f093bc7e367117b3c30c1f8fdd0d9728776381b4d4c86041b554b852907000000043612262624047ee87660be1a707519a443b1c1ce3d248cbfc6c15870f6c5daa2019f5b01d4195ecbc9398fbf3c3b1fa9bb3183301d7a1fb3bd174fcfa40a2b6541ed70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d06820d2a7bc994987302e5b1ac80fc425fe25f8b63169ea78e68fbaaefa59379bbf011d", + "payload": "0100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc880670100000000007f16c5962e8bd963659c793ce370d95f093bc7e367117b3c30c1f8fdd0d9728776381b4d4c86041b554b852907000000043612262624047ee87660be1a707519a443b1c1ce3d248cbfc6c15870f6c5daa2019f5b01d4195ecbc9398fbf3c3b1fa9bb3183301d7a1fb3bd174fcfa40a2b6541ed70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d06820d2a7bc994987302e5b1ac80fc425fe25f8b63169ea78e68fbaaefa59379bbf011d" } } diff --git a/test/messages.js b/test/messages.js index 6cd29d6..b393713 100644 --- a/test/messages.js +++ b/test/messages.js @@ -27,6 +27,7 @@ describe('Messages', function() { Alert: 'alert', Reject: 'reject', Block: 'block', + MerkleBlock: 'merkleblock', FilterLoad: 'filterload', FilterAdd: 'filteradd', FilterClear: 'filterclear', @@ -111,10 +112,13 @@ describe('Messages', function() { var hash = 'eb951630aba498b9a0d10f72b5ea9e39d5ff04b03dc2231e662f52057f948aa1'; [Messages.Inventory, Messages.GetData, Messages.NotFound].forEach(function(clazz) { var b = clazz.forBlock(hash); + var mb = clazz.forMerkleBlock(hash); (b instanceof clazz).should.equal(true); var t = clazz.forTransaction(hash); (t instanceof clazz).should.equal(true); clazz.forBlock(BufferUtils.reverse(new Buffer(hash, 'hex'))).should.deep.equal(b); + clazz.forMerkleBlock(BufferUtils.reverse(new Buffer(hash, 'hex'))).should.deep.equal(mb); + clazz.forFilteredBlock(BufferUtils.reverse(new Buffer(hash, 'hex'))).should.deep.equal(mb); clazz.forTransaction(BufferUtils.reverse(new Buffer(hash, 'hex'))).should.deep.equal(t); }); }); @@ -141,4 +145,10 @@ describe('Messages', function() { msg.getPayload().toString('hex').should.equal(testPayload); }); + it('MerkleBlock#fromBuffer method works', function() { + var testPayload = Data.MERKLEBLOCK.payload; + var msg = new Messages.MerkleBlock().fromBuffer(new Buffer(testPayload, 'hex')); + msg.getPayload().toString('hex').should.equal(testPayload); + }); + });