refactor tx.verify.
This commit is contained in:
parent
af8e3945b7
commit
e51464f29b
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
123
lib/bcoin/tx.js
123
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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -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());
|
||||
|
||||
Loading…
Reference in New Issue
Block a user