diff --git a/lib/bcoin/block.js b/lib/bcoin/block.js index 40435029..ecafb236 100644 --- a/lib/bcoin/block.js +++ b/lib/bcoin/block.js @@ -190,7 +190,75 @@ Block.prototype._buildMerkle = function buildMerkle() { return merkleTree; }; +// This mimics the behavior of CheckBlockHeader() +// and CheckBlock() in bitcoin/src/main.cpp. Block.prototype._checkBlock = function checkBlock() { + // Check proof of work matches claimed amount + if (!utils.testTarget(this.bits, this.hash())) { + return false; + } + + // Check timestamp + if (+new Date(this.ts) > Date.now() + 2 * 60 * 60 * 1000) { + return false; + } + + // Size of all txs cant be bigger than MAX_BLOCK_SIZE + if (this.txs.length > bcoin.protocol.constants.block.maxSize) { + return false; + } + + // First TX must be a coinbase + if (this.txs[0].inputs.length !== 1 || +this.txs[0].inputs[0].out.hash !== 0) { + return false; + } + + // The rest of the txs must not be coinbases + for (var i = 1; i < this.txs.length; i++) { + if (this.txs[i].inputs.length === 1 && +this.txs[i].inputs[0].out.hash === 0) { + return false; + } + } + + // Check transactions + // TODO: + // for (var i = 0; i < this.txs.length; i++) { + // if (!this.txs[i].verify()) { + // return false; + // } + // } + + // Build MerkleTree this.merkleTree = this._buildMerkle(); + + // Check for duplicate tx ids + var unique = []; + for (var i = 0; i < this.txs.length; i++) { + if (!~unique.indexOf(this.txs[i].hash('hex'))) { + unique.push(this.txs[i].hash('hex')); + } + } + if (unique.length !== this.txs.length) { + return false; + } + + // Check to make sure block does not have more opcodes than MAX_BLOCK_SIGOPS + var sigops = 0; + // TODO: + // for (var i = 0; this.txs.length; i++) { + // for (var j = 0; j < this.txs.inputs.length; j++) { + // var script = this.txs.inputs[j].script; + // sigops += countSigops(script); + // } + // for (var j = 0; j < this.txs.outputs.length; j++) { + // var script = this.txs.outputs[j].script; + // sigops += countSigops(script); + // } + // } + if (sigops > bcoin.protocol.constants.block.maxSigops) { + return false; + } + + // Check merkle root return this.merkleTree[this.merkleTree.length-1] === this.merkleRoot; }; diff --git a/lib/bcoin/protocol/constants.js b/lib/bcoin/protocol/constants.js index a3be0e7b..0842b379 100644 --- a/lib/bcoin/protocol/constants.js +++ b/lib/bcoin/protocol/constants.js @@ -147,3 +147,9 @@ exports.hashType = { single: 3, anyonecaypay: 0x80 }; + +exports.block = { + maxSize: 1000000, + maxSigops: 1000000 / 50, + maxOrphanTx: 1000000 / 100 +};