diff --git a/lib/bcoin/chain.js b/lib/bcoin/chain.js index 4df8523d..4c0de3ef 100644 --- a/lib/bcoin/chain.js +++ b/lib/bcoin/chain.js @@ -903,7 +903,7 @@ Chain.prototype._checkInputs = function _checkInputs(block, prev, state, callbac if (!scriptCheck) return next(null, true); - tx.verifyAsync(null, true, state.flags, next); + tx.verifyAsync(state.flags, next); }, function(err, verified) { if (err) return callback(err); diff --git a/lib/bcoin/mempool.js b/lib/bcoin/mempool.js index d2062cae..893c9875 100644 --- a/lib/bcoin/mempool.js +++ b/lib/bcoin/mempool.js @@ -1092,12 +1092,12 @@ Mempool.prototype.verify = function verify(entry, callback) { return callback(new VerifyError(tx, 'invalid', ret.reason, ret.score)); // Do this in the worker pool. - tx.verifyAsync(null, true, flags, function(err, result) { + tx.verifyAsync(flags, function(err, result) { if (err) return callback(err); if (!result) { - return tx.verifyAsync(null, true, mandatory, function(err, result) { + return tx.verifyAsync(mandatory, function(err, result) { if (err) return callback(err); diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 62bfc0a7..576c3bd2 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -567,61 +567,67 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, type) { }; /** - * Verify the transaction inputs. - * @param {Number?} index - Index of output being - * verified. If not present, all outputs will be verified. - * @param {Boolean?} force - Force the transaction to - * be verified, even if it has been confirmed. - * @param {VerifyFlags?} flags + * Verify all transaction inputs. + * @param {VerifyFlags} [flags=STANDARD_VERIFY_FLAGS] * @returns {Boolean} Whether the inputs are valid. */ -TX.prototype.verify = function verify(index, force, flags) { - var i, input; - - // Valid if included in block - if (!force && this.ts !== 0) - return true; +TX.prototype.verify = function verify(flags) { + var i; if (this.inputs.length === 0) return false; - if (index && typeof index === 'object') - index = this.inputs.indexOf(index); - - if (index != null) - assert(this.inputs[index]); - if (this.isCoinbase()) return true; for (i = 0; i < this.inputs.length; i++) { - input = this.inputs[i]; - - if (index != null && i !== index) - continue; - - if (!input.coin) { - bcoin.debug('Warning: Not all coins are available for tx.verify().'); + if (!this.verifyInput(i, flags)) return false; - } + } - try { - Script.verify( - input.script, - input.witness, - input.coin.script, - this, - i, - flags - ); - } catch (e) { - if (e.type === 'ScriptError') - bcoin.debug('Script verification error: %s', e.message); - else - bcoin.debug('Script interpreter threw: %s', e.stack + ''); - return false; - } + return true; +}; + +/** + * Verify a transaction input. + * @param {Number} index - Index of output being + * verified. + * @param {VerifyFlags} [flags=STANDARD_VERIFY_FLAGS] + * @returns {Boolean} Whether the input is valid. + */ + +TX.prototype.verifyInput = function verifyInput(index, flags) { + var input; + + if (typeof index === 'object') + index = this.inputs.indexOf(index); + + input = this.inputs[index]; + + assert(input, 'Input does not exist.'); + + if (!input.coin) { + bcoin.debug('Coin is not available for verification.'); + return false; + } + + try { + Script.verify( + input.script, + input.witness, + input.coin.script, + this, + index, + flags + ); + } catch (e) { + if (e.type === 'ScriptError') + bcoin.debug('Script verification error: %s', e.message); + else + bcoin.error(e); + + return false; } return true; @@ -630,39 +636,40 @@ TX.prototype.verify = function verify(index, force, flags) { /** * Verify the transaction inputs on the worker pool * (if workers are enabled). - * @param {Number?} index - Index of output being - * verified. If not present, all outputs will be verified. - * @param {Boolean?} force - Force the transaction to - * be verified, even if it has been confirmed. - * @param {VerifyFlags?} flags + * @param {VerifyFlags?} [flags=STANDARD_VERIFY_FLAGS] * @param {Function} callback * @returns {Boolean} Whether the inputs are valid. */ -TX.prototype.verifyAsync = function verifyAsync(index, force, flags, callback) { - var res; +TX.prototype.verifyAsync = function verifyAsync(flags, callback) { + var result; - callback = utils.asyncify(callback); + if (typeof flags === 'function') { + callback = flags; + flags = null; + } if (!bcoin.workerPool) { + callback = utils.asyncify(callback); try { - res = this.verify(index, force, flags); + result = this.verify(flags); } catch (e) { return callback(e); } - return callback(null, res); + return callback(null, result); } - if (!force && this.ts !== 0) - return callback(null, true); - - if (this.inputs.length === 0) + if (this.inputs.length === 0) { + callback = utils.asyncify(callback); return callback(null, false); + } - if (this.isCoinbase()) + if (this.isCoinbase()) { + callback = utils.asyncify(callback); return callback(null, true); + } - bcoin.workerPool.verify(this, index, force, flags, callback); + bcoin.workerPool.verify(this, flags, callback); }; /** diff --git a/lib/bcoin/txdb.js b/lib/bcoin/txdb.js index 0267896c..5c557168 100644 --- a/lib/bcoin/txdb.js +++ b/lib/bcoin/txdb.js @@ -367,7 +367,7 @@ TXDB.prototype._add = function add(tx, map, callback, force) { // Skip invalid transactions if (self.options.verify) { - if (!tx.verify(i)) + if (!tx.verifyInput(i)) return callback(null, false); } @@ -406,7 +406,7 @@ TXDB.prototype._add = function add(tx, map, callback, force) { // Skip invalid transactions if (self.options.verify) { - if (!tx.verify(i)) + if (!tx.verifyInput(i)) return callback(null, false, map); } @@ -488,7 +488,7 @@ TXDB.prototype._add = function add(tx, map, callback, force) { return next(); } - if (orphan.tx.verify(orphan.index)) { + if (orphan.tx.verifyInput(orphan.index)) { some = true; return next(); } diff --git a/lib/bcoin/workers.js b/lib/bcoin/workers.js index 37a6663a..410007b4 100644 --- a/lib/bcoin/workers.js +++ b/lib/bcoin/workers.js @@ -247,14 +247,12 @@ Workers.prototype.execute = function execute(method, args, timeout, callback) { /** * Execute the tx verification job (default timeout). * @param {TX} tx - * @param {Number} index - * @param {Boolean} force * @param {VerifyFlags} flags * @param {Function} callback - Returns [Error, Boolean]. */ -Workers.prototype.verify = function verify(tx, index, force, flags, callback) { - return this.execute('verify', [tx, index, force, flags], -1, callback); +Workers.prototype.verify = function verify(tx, flags, callback) { + return this.execute('verify', [tx, flags], -1, callback); }; /** @@ -698,14 +696,12 @@ jobs = {}; * Execute tx.verify() on worker. * @see TX#verify * @param {TX} tx - * @param {Number?} index - * @param {Boolean?} force - * @param {VerifyFlags?} flags + * @param {VerifyFlags} flags * @returns {Boolean} */ -jobs.verify = function verify(tx, index, force, flags) { - return tx.verify(index, force, flags); +jobs.verify = function verify(tx, flags) { + return tx.verify(flags); }; /** diff --git a/test/block-test.js b/test/block-test.js index d1d940be..c4624df0 100644 --- a/test/block-test.js +++ b/test/block-test.js @@ -77,7 +77,7 @@ describe('Block', function() { assert(b.verify()); }); - it('should be jsonified and unjsonified and still verify', function() { + it('should be serialized and deserialized and still verify', function() { var raw = mblock.toRaw(); var b = bcoin.merkleblock.fromRaw(raw); assert.deepEqual(b.render(), raw); @@ -132,7 +132,7 @@ describe('Block', function() { var tx = block.txs[i]; assert(tx.isSane()); assert(tx.checkInputs(block.height)); - assert(tx.verify(null, true, flags)); + assert(tx.verify(flags)); } assert.equal(block.getReward(), 2507773345); assert.equal(block.getReward(), block.txs[0].outputs[0].value); diff --git a/test/tx-test.js b/test/tx-test.js index b889aec0..566b7559 100644 --- a/test/tx-test.js +++ b/test/tx-test.js @@ -132,27 +132,27 @@ describe('TX', function() { it('should verify non-minimal output' + suffix, function() { clearCache(tx1, nocache); - assert(tx1.verify(null, true, constants.flags.VERIFY_P2SH)); + assert(tx1.verify(constants.flags.VERIFY_P2SH)); }); it('should verify tx.version == 0' + suffix, function() { clearCache(tx2, nocache); - assert(tx2.verify(null, true, constants.flags.VERIFY_P2SH)); + assert(tx2.verify(constants.flags.VERIFY_P2SH)); }); it('should verify sighash_single bug w/ findanddelete' + suffix, function() { clearCache(tx3, nocache); - assert(tx3.verify(null, true, constants.flags.VERIFY_P2SH)); + assert(tx3.verify(constants.flags.VERIFY_P2SH)); }); it('should verify high S value with only DERSIG enabled' + suffix, function() { clearCache(tx4, nocache); - assert(tx4.verify(0, true, constants.flags.VERIFY_P2SH | constants.flags.VERIFY_DERSIG)); + assert(tx4.verifyInput(0, constants.flags.VERIFY_P2SH | constants.flags.VERIFY_DERSIG)); }); it('should verify the coolest tx ever sent' + suffix, function() { clearCache(coolest, nocache); - assert(coolest.verify(null, true, constants.flags.VERIFY_NONE)); + assert(coolest.verify(constants.flags.VERIFY_NONE)); }); it('should parse witness tx properly', function() { @@ -249,13 +249,13 @@ describe('TX', function() { } it('should handle valid tx test' + suffix + ': ' + comments, function() { clearCache(tx, nocache); - assert.ok(tx.verify(null, true, flags)); + assert.ok(tx.verify(flags)); }); } else { if (comments === 'Duplicate inputs') { it('should handle duplicate input test' + suffix + ': ' + comments, function() { clearCache(tx, nocache); - assert.ok(tx.verify(null, true, flags)); + assert.ok(tx.verify(flags)); assert.ok(!tx.isSane()); }); return; @@ -263,7 +263,7 @@ describe('TX', function() { if (comments === 'Negative output') { it('should handle invalid tx (negative)' + suffix + ': ' + comments, function() { clearCache(tx, nocache); - assert.ok(tx.verify(null, true, flags)); + assert.ok(tx.verify(flags)); assert.ok(!tx.isSane()); }); return; @@ -277,7 +277,7 @@ describe('TX', function() { } it('should handle invalid tx test' + suffix + ': ' + comments, function() { clearCache(tx, nocache); - assert.ok(!tx.verify(null, true, flags)); + assert.ok(!tx.verify(flags)); }); } }); diff --git a/test/wallet-test.js b/test/wallet-test.js index ed01c86b..f697afec 100644 --- a/test/wallet-test.js +++ b/test/wallet-test.js @@ -125,7 +125,7 @@ describe('Wallet', function() { w.sign(tx, function(err) { assert.ifError(err); - assert(tx.verify(null, true, flags)); + assert(tx.verify(flags)); cb(); }); }); @@ -649,18 +649,18 @@ describe('Wallet', function() { // Create a tx requiring 2 signatures var send = bcoin.mtx(); send.addOutput({ address: receive.getAddress(), value: 5460 }); - assert(!send.verify(null, true, flags)); + assert(!send.verify(flags)); w1.fill(send, { rate: 10000, round: true }, function(err) { assert.ifError(err); w1.sign(send, function(err) { assert.ifError(err); - assert(!send.verify(null, true, flags)); + assert(!send.verify(flags)); w2.sign(send, function(err) { assert.ifError(err); - assert(send.verify(null, true, flags)); + assert(send.verify(flags)); assert.equal(w1.changeDepth, 1); var change = w1.changeAddress.getAddress(); @@ -695,7 +695,7 @@ describe('Wallet', function() { else send.inputs[0].script.code[2] = 0; - assert(!send.verify(null, true, flags)); + assert(!send.verify(flags)); assert.equal(send.getFee(), 10000); // w3 = bcoin.wallet.fromJSON(w3.toJSON());