check sequence locks.

This commit is contained in:
Christopher Jeffrey 2016-05-05 19:41:14 -07:00
parent e2bcbcaba5
commit 5fd44dbed8
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD

View File

@ -434,7 +434,7 @@ Chain.prototype._preload = function _preload(callback) {
Chain.prototype._verifyContext = function _verifyContext(block, prev, callback) { Chain.prototype._verifyContext = function _verifyContext(block, prev, callback) {
var self = this; var self = this;
this._verify(block, prev, function(err, flags) { this._verify(block, prev, function(err, state) {
if (err) if (err)
return callback(err); return callback(err);
@ -442,7 +442,7 @@ Chain.prototype._verifyContext = function _verifyContext(block, prev, callback)
if (err) if (err)
return callback(err); return callback(err);
self._checkInputs(block, prev, flags, function(err) { self._checkInputs(block, prev, state, function(err) {
if (err) if (err)
return callback(err); return callback(err);
@ -577,7 +577,7 @@ Chain.prototype._verify = function _verify(block, prev, callback) {
} }
} }
return done(null, state.flags); return done(null, state);
}); });
}); });
}; };
@ -786,11 +786,11 @@ Chain.prototype._findDuplicates = function _findDuplicates(block, prev, callback
* @see TX#checkInputs * @see TX#checkInputs
* @param {Block} block * @param {Block} block
* @param {ChainBlock} prev * @param {ChainBlock} prev
* @param {VerifyFlags} flags * @param {DeploymentState} state
* @param {Function} callback - Returns [{@link VerifyError}]. * @param {Function} callback - Returns [{@link VerifyError}].
*/ */
Chain.prototype._checkInputs = function _checkInputs(block, prev, flags, callback) { Chain.prototype._checkInputs = function _checkInputs(block, prev, state, callback) {
var self = this; var self = this;
var height = prev.height + 1; var height = prev.height + 1;
var scriptCheck = true; var scriptCheck = true;
@ -813,103 +813,90 @@ Chain.prototype._checkInputs = function _checkInputs(block, prev, flags, callbac
this.db.fillBlock(block, function(err) { this.db.fillBlock(block, function(err) {
var ret = {}; var ret = {};
var sigops = 0; var sigops = 0;
var i, j, input, tx, hash;
if (err) if (err)
return callback(err); return callback(err);
// Check all transactions // Check all transactions
for (i = 0; i < block.txs.length; i++) { utils.forEachSerial(block.txs, function(tx, next) {
tx = block.txs[i]; var hash = tx.hash('hex');
hash = tx.hash('hex');
// Count sigops (legacy + scripthash? + witness?) // Ensure tx is not double spending an output.
sigops += tx.getSigopsCost(flags); if (!tx.isCoinbase()) {
if (!tx.hasCoins()) {
if (sigops > constants.block.MAX_SIGOPS_COST) {
return callback(new VerifyError(block,
'invalid',
'bad-blk-sigops',
100));
}
// Coinbases do not have prevouts.
if (tx.isCoinbase())
continue;
for (j = 0; j < tx.inputs.length; j++) {
input = tx.inputs[j];
// Ensure tx is not double spending an output.
if (!input.coin) {
assert(!historical, 'BUG: Spent inputs in historical data!'); assert(!historical, 'BUG: Spent inputs in historical data!');
return callback(new VerifyError(block, return next(new VerifyError(block,
'invalid', 'invalid',
'bad-txns-inputs-missingorspent', 'bad-txns-inputs-missingorspent',
100)); 100));
} }
}
if (!self.options.verifySync) self.checkLocks(tx, state.lockFlags, entry, function(err, valid) {
continue; if (err)
return next(err);
if (!valid) {
return next(new VerifyError(block,
'invalid',
'bad-txns-nonfinal',
100));
}
// Count sigops (legacy + scripthash? + witness?)
sigops += tx.getSigopsCost(state.flags);
if (sigops > constants.block.MAX_SIGOPS_COST) {
return next(new VerifyError(block,
'invalid',
'bad-blk-sigops',
100));
}
// Contextual sanity checks.
if (!tx.isCoinbase()) {
if (!tx.checkInputs(height, ret)) {
return next(new VerifyError(block,
'invalid',
ret.reason,
ret.score));
}
}
return next();
});
}, function(err) {
if (err)
return callback(err);
// Verify all txs in parallel.
utils.every(block.txs, function(tx, next) {
if (!scriptCheck) if (!scriptCheck)
continue; return next(null, true);
// Verify the scripts tx.verifyAsync(null, true, state.flags, next);
if (!tx.verify(j, true, flags)) { }, function(err, verified) {
bcoin.debug( if (err)
'Transaction failed consensus verification: %s', return callback(err);
tx.rhash);
bcoin.debug('TX:'); if (!verified) {
bcoin.debug(tx);
bcoin.debug('Input (%d):', j);
bcoin.debug(input);
bcoin.debug('Serialized TX (with coins):');
bcoin.debug(tx.toExtended('hex', true));
bcoin.debug('Flags: %d', flags);
assert(!historical, 'BUG: Invalid inputs in historical data!'); assert(!historical, 'BUG: Invalid inputs in historical data!');
return callback(new VerifyError(block, return next(new VerifyError(block,
'invalid', 'invalid',
'mandatory-script-verify-flag-failed', 'mandatory-script-verify-flag-failed',
100)); 100));
} }
}
// Contextual sanity checks. // Make sure the miner isn't trying to conjure more coins.
if (!tx.checkInputs(height, ret)) { if (block.getClaimed().cmp(block.getReward()) > 0) {
return callback(new VerifyError(block, return callback(new VerifyError(block,
'invalid', 'invalid',
ret.reason, 'bad-cb-amount',
ret.score)); 100));
} }
}
// Make sure the miner isn't trying to conjure more coins. return callback();
if (block.getClaimed().cmp(block.getReward()) > 0) });
return callback(new VerifyError(block, 'invalid', 'bad-cb-amount', 100));
if (self.options.verifySync)
return callback();
if (!scriptCheck)
return callback();
// Verify all txs in parallel.
utils.every(block.txs, function(tx, next) {
tx.verifyAsync(null, true, flags, next);
}, function(err, verified) {
if (err)
return callback(err);
if (!verified) {
assert(!historical, 'BUG: Invalid inputs in historical data!');
return callback(new VerifyError(block,
'invalid',
'mandatory-script-verify-flag-failed',
100));
}
return callback();
}); });
}); });
}; };
@ -2470,7 +2457,7 @@ Chain.prototype.getLocks = function getLocks(tx, flags, entry, callback) {
var minTime = -1; var minTime = -1;
var coinHeight; var coinHeight;
if (tx.version < 2 || !hasFlag) if (tx.isCoinbase() || tx.version < 2 || !hasFlag)
return utils.asyncify(callback)(null, minHeight, minTime); return utils.asyncify(callback)(null, minHeight, minTime);
utils.forEachSerial(tx.inputs, function(input, next) { utils.forEachSerial(tx.inputs, function(input, next) {
@ -2555,7 +2542,6 @@ Chain.prototype.checkLocks = function checkLocks(tx, flags, entry, callback) {
}); });
}; };
/** /**
* Calculate the difficulty. * Calculate the difficulty.
* @param {ChainBlock} entry * @param {ChainBlock} entry