diff --git a/lib/bcoin/bip152.js b/lib/bcoin/bip152.js index 154eabc1..b1f7e9f0 100644 --- a/lib/bcoin/bip152.js +++ b/lib/bcoin/bip152.js @@ -168,7 +168,7 @@ CompactBlock.prototype.toRaw = function toRaw(witness, writer) { }; CompactBlock.prototype.toRequest = function toRequest() { - return BlockTXRequest.fromCompact(this); + return TXRequest.fromCompact(this); }; CompactBlock.prototype.fillMempool = function fillMempool(mempool, callback) { @@ -218,7 +218,7 @@ CompactBlock.prototype.fillMempool = function fillMempool(mempool, callback) { }); }; -CompactBlock.prototype.fillMissing = function fillMissing(missing) { +CompactBlock.prototype.fillMissing = function fillMissing(res) { var offset = 0; var i; @@ -226,13 +226,13 @@ CompactBlock.prototype.fillMissing = function fillMissing(missing) { if (this.available[i]) continue; - if (offset >= missing.length) + if (offset >= res.txs.length) return false; - this.available = missing[offset++]; + this.available[i] = res.txs[offset++]; } - return offset === missing.length; + return offset === res.txs.length; }; CompactBlock.prototype.sid = function sid(hash) { @@ -374,9 +374,9 @@ CompactBlock.prototype.stopTimeout = function stopTimeout() { * @constructor */ -function BlockTXRequest(options) { - if (!(this instanceof BlockTXRequest)) - return new BlockTXRequest(options); +function TXRequest(options) { + if (!(this instanceof TXRequest)) + return new TXRequest(options); this.hash = null; this.indexes = []; @@ -385,7 +385,7 @@ function BlockTXRequest(options) { this.fromOptions(options); } -BlockTXRequest.prototype.fromOptions = function fromOptions(options) { +TXRequest.prototype.fromOptions = function fromOptions(options) { this.hash = options.hash; if (options.indexes) @@ -394,11 +394,11 @@ BlockTXRequest.prototype.fromOptions = function fromOptions(options) { return this; }; -BlockTXRequest.fromOptions = function fromOptions(options) { - return new BlockTXRequest().fromOptions(options); +TXRequest.fromOptions = function fromOptions(options) { + return new TXRequest().fromOptions(options); }; -BlockTXRequest.prototype.fromCompact = function fromCompact(block) { +TXRequest.prototype.fromCompact = function fromCompact(block) { var i; this.hash = block.hash('hex'); @@ -411,11 +411,11 @@ BlockTXRequest.prototype.fromCompact = function fromCompact(block) { return this; }; -BlockTXRequest.fromCompact = function fromCompact(block) { - return new BlockTXRequest().fromCompact(block); +TXRequest.fromCompact = function fromCompact(block) { + return new TXRequest().fromCompact(block); }; -BlockTXRequest.prototype.fromRaw = function fromRaw(data) { +TXRequest.prototype.fromRaw = function fromRaw(data) { var p = bcoin.reader(data); var i, count, index, offset; @@ -442,11 +442,11 @@ BlockTXRequest.prototype.fromRaw = function fromRaw(data) { return this; }; -BlockTXRequest.fromRaw = function fromRaw(data) { - return new BlockTXRequest().fromRaw(data); +TXRequest.fromRaw = function fromRaw(data) { + return new TXRequest().fromRaw(data); }; -BlockTXRequest.prototype.toRaw = function toRaw(writer) { +TXRequest.prototype.toRaw = function toRaw(writer) { var p = bcoin.writer(writer); var i, index; @@ -471,9 +471,9 @@ BlockTXRequest.prototype.toRaw = function toRaw(writer) { * @constructor */ -function BlockTX(options) { - if (!(this instanceof BlockTX)) - return new BlockTX(options); +function TXResponse(options) { + if (!(this instanceof TXResponse)) + return new TXResponse(options); this.hash = null; this.txs = []; @@ -482,7 +482,7 @@ function BlockTX(options) { this.fromOptions(options); } -BlockTX.prototype.fromOptions = function fromOptions(options) { +TXResponse.prototype.fromOptions = function fromOptions(options) { this.hash = options.hash; if (options.txs) @@ -491,11 +491,11 @@ BlockTX.prototype.fromOptions = function fromOptions(options) { return this; }; -BlockTX.fromOptions = function fromOptions(options) { - return new BlockTX().fromOptions(options); +TXResponse.fromOptions = function fromOptions(options) { + return new TXResponse().fromOptions(options); }; -BlockTX.prototype.fromRaw = function fromRaw(data) { +TXResponse.prototype.fromRaw = function fromRaw(data) { var p = bcoin.reader(data); var i, count; @@ -509,30 +509,30 @@ BlockTX.prototype.fromRaw = function fromRaw(data) { return this; }; -BlockTX.fromRaw = function fromRaw(data) { - return new BlockTX().fromRaw(data); +TXResponse.fromRaw = function fromRaw(data) { + return new TXResponse().fromRaw(data); }; -BlockTX.prototype.fromBlock = function fromBlock(block, request) { +TXResponse.prototype.fromBlock = function fromBlock(block, req) { var i, index; - this.hash = request.hash; + this.hash = req.hash; - for (i = 0; i < request.indexes.length; i++) { - index = request.indexes[i]; + for (i = 0; i < req.indexes.length; i++) { + index = req.indexes[i]; if (index >= block.txs.length) - return; + return this; this.txs.push(block.txs[index]); } return this; }; -BlockTX.fromBlock = function fromBlock(block, request) { - return new BlockTX().fromBlock(block, request); +TXResponse.fromBlock = function fromBlock(block, req) { + return new TXResponse().fromBlock(block, req); }; -BlockTX.prototype.toRaw = function toRaw(witness, writer) { +TXResponse.prototype.toRaw = function toRaw(witness, writer) { var p = bcoin.writer(writer); var i, tx; @@ -597,6 +597,6 @@ SendCompact.prototype.toRaw = function toRaw(writer) { */ exports.CompactBlock = CompactBlock; -exports.BlockTXRequest = BlockTXRequest; -exports.BlockTX = BlockTX; +exports.TXRequest = TXRequest; +exports.TXResponse = TXResponse; exports.SendCompact = SendCompact; diff --git a/lib/bcoin/peer.js b/lib/bcoin/peer.js index 1e578460..19bcf1f7 100644 --- a/lib/bcoin/peer.js +++ b/lib/bcoin/peer.js @@ -1919,16 +1919,16 @@ Peer.prototype._handleCmpctBlock = function _handleCmpctBlock(block) { * @param {Object} */ -Peer.prototype._handleGetBlockTxn = function _handleGetBlockTxn(payload) { +Peer.prototype._handleGetBlockTxn = function _handleGetBlockTxn(req) { var self = this; - var blockTX; + var res; function done(err) { if (err) { self.emit('error', err); return; } - self.fire('blocktxn', payload); + self.fire('blocktxn', req); } if (this.chain.db.options.spv) @@ -1940,7 +1940,7 @@ Peer.prototype._handleGetBlockTxn = function _handleGetBlockTxn(payload) { if (this.pool.options.selfish) return done(); - this.chain.db.getBlock(payload.hash, function(err, block) { + this.chain.db.getBlock(req.hash, function(err, block) { if (err) return done(err); @@ -1959,9 +1959,9 @@ Peer.prototype._handleGetBlockTxn = function _handleGetBlockTxn(payload) { return done(); } - blockTX = bcoin.bip152.BlockTX.fromBlock(block, payload); + res = bcoin.bip152.TXResponse.fromBlock(block, req); - self.write(self.framer.blockTxn(blockTX)); + self.write(self.framer.blockTxn(res)); done(); }); @@ -1973,20 +1973,20 @@ Peer.prototype._handleGetBlockTxn = function _handleGetBlockTxn(payload) { * @param {Object} */ -Peer.prototype._handleBlockTxn = function _handleBlockTxn(payload) { - var block = this.compactBlocks[payload.hash]; +Peer.prototype._handleBlockTxn = function _handleBlockTxn(res) { + var block = this.compactBlocks[res.hash]; if (!block) { this.logger.info('Peer sent unsolicited blocktxn (%s).', this.hostname); return; } - this.fire('getblocktxn', payload); + this.fire('getblocktxn', res); block.stopTimeout(); - delete this.compactBlocks[payload.hash]; + delete this.compactBlocks[res.hash]; - if (!block.fillMissing(payload.txs)) { + if (!block.fillMissing(res)) { this.setMisbehavior(100); this.logger.info('Peer sent non-full blocktxn (%s).', this.hostname); return; diff --git a/test/block-test.js b/test/block-test.js index ece552f0..15424f25 100644 --- a/test/block-test.js +++ b/test/block-test.js @@ -242,4 +242,59 @@ describe('Block', function() { cb(); }); }); + + it('should handle half-full compact block', function(cb) { + var cblock = bip152.CompactBlock.fromRaw(cmpct[0], 'hex'); + var block = bcoin.block.fromRaw(cmpct[1], 'hex'); + var cblock2 = bip152.CompactBlock.fromBlock(block, cblock.keyNonce); + var map = {}; + + assert.equal(cblock.toRaw().toString('hex'), cmpct[0]); + assert.equal(cblock2.toRaw().toString('hex'), cmpct[0]); + + for (var i = 0; i < block.txs.length; i++) { + var tx = block.txs[i]; + map[tx.hash('hex')] = tx; + } + + var mid = block.txs.length >>> 1; + var keys = Object.keys(map).slice(0, mid); + + var fakeMempool = { + getSnapshot: function(callback) { + callback(null, keys); + }, + getTX: function(hash, callback) { + callback(null, map[hash]); + } + }; + + assert.equal(cblock.sid(block.txs[1].hash()), 125673511480291); + + cblock.fillMempool(fakeMempool, function(err, result) { + assert.ifError(err); + assert(!result); + + var req = cblock.toRequest(); + assert.equal(req.hash, cblock.hash('hex')); + assert.deepEqual(req.indexes, [5, 6, 7, 8, 9]); + + req = bip152.TXRequest.fromRaw(req.toRaw()); + assert.equal(req.hash, cblock.hash('hex')); + assert.deepEqual(req.indexes, [5, 6, 7, 8, 9]); + + var res = bip152.TXResponse.fromBlock(block, req); + res = bip152.TXResponse.fromRaw(res.toRaw()); + + var result = cblock.fillMissing(res); + assert(result); + + for (var i = 0; i < cblock.available.length; i++) + assert(cblock.available[i]); + + assert.equal(cblock.toBlock().toRaw().toString('hex'), block.toRaw().toString('hex')); + + cb(); + }); + }); });