diff --git a/lib/net/bip152.js b/lib/net/bip152.js index 03456147..5bed4ed5 100644 --- a/lib/net/bip152.js +++ b/lib/net/bip152.js @@ -250,14 +250,17 @@ CompactBlock.prototype.fillMissing = function fillMissing(res) { }; CompactBlock.prototype.sid = function sid(hash) { + var lo, hi; + if (typeof hash === 'string') hash = new Buffer(hash, 'hex'); hash = siphash(hash, this.sipKey); - return hash.readUInt32LE(0, true) - + hash.readUInt16LE(4, true) - * 0x100000000; + lo = hash.readUInt32LE(0, true); + hi = hash.readUInt16LE(4, true); + + return hi * 0x100000000 + lo; }; CompactBlock.prototype.hasIndex = function hasIndex(index) { @@ -265,14 +268,8 @@ CompactBlock.prototype.hasIndex = function hasIndex(index) { }; CompactBlock.prototype.initKey = function initKey() { - var data = new Buffer(88); - var hash; - - this.abbr().copy(data, 0); - this.keyNonce.copy(data, 80); - - hash = crypto.sha256(data); - + var data = util.concat(this.abbr(), this.keyNonce); + var hash = crypto.sha256(data); this.sipKey = hash.slice(0, 16); }; @@ -332,13 +329,14 @@ CompactBlock.prototype.toBlock = function toBlock() { block.bits = this.bits; block.nonce = this.nonce; block.totalTX = this.totalTX; - block.txs = new Array(this.ptx.length); block._hash = this._hash; + block._hhash = this._hhash; + block._validHeaders = this._validHeaders; for (i = 0; i < this.available.length; i++) { tx = this.available[i]; assert(tx, 'Compact block is not full.'); - block.txs[i] = tx; + block.txs.push(tx); } return block; @@ -354,6 +352,10 @@ CompactBlock.prototype.fromBlock = function fromBlock(block, witness, nonce) { this.bits = block.bits; this.nonce = block.nonce; this.totalTX = block.totalTX; + this._hash = block._hash; + this._hhash = block._hhash; + this._validHeaders = true; + this._valid = true; if (!nonce) nonce = util.nonce(); diff --git a/lib/net/peer.js b/lib/net/peer.js index c91c3fe4..504a8e68 100644 --- a/lib/net/peer.js +++ b/lib/net/peer.js @@ -15,7 +15,6 @@ var co = require('../utils/co'); var Parser = require('./parser'); var Framer = require('./framer'); var packets = require('./packets'); -var packetTypes = packets.types; var NetworkAddress = require('../primitives/netaddress'); var constants = require('../protocol/constants'); var InvItem = require('../primitives/invitem'); @@ -26,6 +25,9 @@ var BIP150 = require('./bip150'); var BIP152 = require('./bip152'); var Block = require('../primitives/block'); var TX = require('../primitives/tx'); +var errors = require('../btc/errors'); +var packetTypes = packets.types; +var VerifyResult = errors.VerifyResult; /** * Represents a remote peer. @@ -2280,6 +2282,7 @@ Peer.prototype._handleSendCmpct = function _handleSendCmpct(packet) { Peer.prototype._handleCmpctBlock = co(function* _handleCmpctBlock(packet) { var block = packet.block; var hash = block.hash('hex'); + var ret = new VerifyResult(); var result; if (!this.options.compact) { @@ -2299,6 +2302,14 @@ Peer.prototype._handleCmpctBlock = co(function* _handleCmpctBlock(packet) { return; } + if (!block.verify(ret)) { + this.logger.debug( + 'Peer sent an invalid compact block (%s).', + this.hostname); + this.reject(block, 'invalid', ret.reason, ret.score); + return; + } + result = block.fillMempool(this.options.witness, this.mempool); if (result) { diff --git a/lib/net/pool.js b/lib/net/pool.js index 67b7b03b..d37276d8 100644 --- a/lib/net/pool.js +++ b/lib/net/pool.js @@ -15,8 +15,6 @@ var IP = require('../utils/ip'); var co = require('../utils/co'); var constants = require('../protocol/constants'); var errors = require('../btc/errors'); -var VerifyError = errors.VerifyError; -var VerifyResult = errors.VerifyResult; var NetworkAddress = require('../primitives/netaddress'); var Address = require('../primitives/address'); var BIP150 = require('./bip150'); @@ -29,6 +27,8 @@ var Peer = require('./peer'); var TX = require('../primitives/tx'); var tcp = require('./tcp'); var request = require('../http/request'); +var VerifyError = errors.VerifyError; +var VerifyResult = errors.VerifyResult; /** * A pool of peers for handling all network activity. diff --git a/lib/primitives/block.js b/lib/primitives/block.js index da38d0d2..f2d71942 100644 --- a/lib/primitives/block.js +++ b/lib/primitives/block.js @@ -677,7 +677,7 @@ Block.prototype.getJSON = function getJSON(network, view, height) { nonce: this.nonce, totalTX: this.totalTX, txs: this.txs.map(function(tx, i) { - return tx.getJSON(network, view, this, i); + return tx.getJSON(network, view, null, i); }, this) }; }; diff --git a/lib/primitives/headers.js b/lib/primitives/headers.js index d8de2685..bad7ae05 100644 --- a/lib/primitives/headers.js +++ b/lib/primitives/headers.js @@ -205,6 +205,7 @@ Headers.prototype.toHeaders = function toHeaders() { Headers.fromBlock = function fromBlock(block) { var headers = new Headers(block); headers._hash = block._hash; + headers._hhash = block._hhash; headers._valid = true; return headers; }; diff --git a/lib/primitives/memblock.js b/lib/primitives/memblock.js index 73ab7c5b..ead6c0f0 100644 --- a/lib/primitives/memblock.js +++ b/lib/primitives/memblock.js @@ -166,6 +166,7 @@ MemBlock.prototype.toNormal = function toNormal() { MemBlock.prototype.toBlock = function toBlock() { var block = Block.fromRaw(this._raw); block._hash = this._hash; + block._hhash = this._hhash; block._cbHeight = this._cbHeight; block._validHeaders = this._validHeaders; this._raw = null; diff --git a/lib/primitives/merkleblock.js b/lib/primitives/merkleblock.js index 3eb9779f..6aed1d37 100644 --- a/lib/primitives/merkleblock.js +++ b/lib/primitives/merkleblock.js @@ -654,6 +654,7 @@ MerkleBlock.fromMatches = function fromMatches(block, matches) { merkle = new MerkleBlock(); merkle._hash = block._hash; + merkle._hhash = block._hhash; merkle.version = block.version; merkle.prevBlock = block.prevBlock; merkle.merkleRoot = block.merkleRoot; diff --git a/test/block-test.js b/test/block-test.js index 313466df..0bfe112e 100644 --- a/test/block-test.js +++ b/test/block-test.js @@ -154,6 +154,7 @@ describe('Block', function() { it('should verify a historical block', function() { var view = new CoinView(); var height = block300025.height; + var sigops = 0; var i, j, tx, input, coin, flags; for (i = 1; i < block300025.txs.length; i++) { @@ -176,12 +177,14 @@ describe('Block', function() { for (i = 1; i < block.txs.length; i++) { tx = block.txs[i]; assert(tx.isSane()); - assert(tx.checkInputs(view, block300025.height)); + assert(tx.checkInputs(view, height)); assert(tx.verify(view, flags)); assert(!tx.hasWitness()); + sigops += tx.getSigopsWeight(view, flags); view.addTX(tx, height); } + assert.equal(sigops, 5280); assert.equal(block.getReward(view, height), 2507773345); assert.equal(block.getReward(view, height), block.txs[0].outputs[0].value); }); @@ -198,6 +201,7 @@ describe('Block', function() { block2._valid = null; block2._validHeaders = null; block2._hash = null; + block2._hhash = null; block2.merkleRoot = block.merkleRoot; assert(block2.verify()); }); @@ -213,6 +217,7 @@ describe('Block', function() { mblock2._validHeaders = null; mblock2._validPartial = null; mblock2._hash = null; + mblock2._hhash = null; mblock2.merkleRoot = mblock.merkleRoot; assert(mblock2.verify()); }); @@ -227,6 +232,7 @@ describe('Block', function() { block2._valid = null; block2._validHeaders = null; block2._hash = null; + block2._hhash = null; block2.bits = block.bits; assert(block2.verify()); });