tx/mempool: fix mutated witnesses in rejects filter.

This commit is contained in:
Christopher Jeffrey 2016-09-19 04:41:29 -07:00
parent 27e574c7e5
commit c0f4225b32
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
4 changed files with 159 additions and 7 deletions

View File

@ -815,11 +815,21 @@ Mempool.prototype.verify = function verify(entry, callback) {
0));
}
if (self.requireStandard && !tx.hasStandardInputs()) {
return callback(new VerifyError(tx,
'nonstandard',
'bad-txns-nonstandard-inputs',
0));
if (self.requireStandard) {
if (!tx.hasStandardInputs()) {
return callback(new VerifyError(tx,
'nonstandard',
'bad-txns-nonstandard-inputs',
0));
}
// if (self.chain.state.hasWitness()) {
// if (!tx.hasStandardWitness()) {
// return callback(new VerifyError(tx,
// 'nonstandard',
// 'bad-witness-nonstandard',
// 0));
// }
// }
}
if (tx.getSigopsWeight(flags) > constants.tx.MAX_SIGOPS_WEIGHT) {

View File

@ -1359,7 +1359,13 @@ Pool.prototype._handleTX = function _handleTX(tx, peer, callback) {
if (err.type === 'VerifyError') {
if (err.score !== -1)
peer.reject(tx, err.code, err.reason, err.score);
self.rejectsFilter.add(tx.hash());
// Once we test it more, we can do:
// if (err.reason !== 'bad-witness-nonstandard')
if (!tx.hasWitness())
self.rejectsFilter.add(tx.hash());
return callback(err);
}
return callback(err);

View File

@ -1359,6 +1359,138 @@ TX.prototype.hasStandardInputs = function hasStandardInputs() {
return true;
};
/**
* Perform contextual checks to verify coin and witness standardness.
* @see IsBadWitness()
* @returns {Boolean}
*/
TX.prototype.hasStandardWitness = function hasStandardWitness(strict) {
var i, j, input, prev, hash, redeem, m, n;
if (this.isCoinbase())
return true;
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
if (!input.coin)
continue;
prev = input.coin.script;
if (prev.isScripthash()) {
prev = input.script.getRedeem();
if (!prev)
return false;
}
if (!prev.isProgram()) {
if (input.witness.length !== 0)
return false;
continue;
}
if (prev.isWitnessPubkeyhash()) {
if (input.witness.length !== 2)
return false;
if (input.witness.get(0).length > 73)
return false;
hash = crypto.hash160(input.witness.get(1));
if (!utils.equal(hash, prev.get(1)))
return false;
continue;
}
if (!prev.isWitnessScripthash()) {
// Unknown program type,
// let it through for now.
continue;
}
if (input.witness.length === 0)
return false;
// Based on Johnson Lau's calculations:
if (input.witness.length - 1 > 604)
return false;
if (strict) {
if (input.witness.length - 1 > constants.script.MAX_P2WSH_STACK)
return false;
}
for (j = 0; j < input.witness.length; j++) {
if (input.witness.get(j).length > constants.script.MAX_PUSH)
return false;
if (strict) {
if (input.witness.get(j).length > constants.script.MAX_P2WSH_PUSH)
return false;
}
}
redeem = input.witness.get(input.witness.length - 1);
if (redeem.length > constants.script.MAX_SIZE)
return false;
if (strict) {
if (redeem.length > constants.script.MAX_P2WSH_SIZE)
return false;
}
hash = crypto.sha256(redeem);
if (!utils.equal(hash, prev.get(1)))
return false;
redeem = new bcoin.script(redeem);
if (redeem.isPubkey()) {
if (input.witness.length - 1 !== 1)
return false;
if (input.witness.get(0).length > 73)
return false;
continue;
}
if (redeem.isPubkeyhash()) {
if (input.witness.length - 1 !== 2)
return false;
if (input.witness.get(0).length > 73)
return false;
continue;
}
if (redeem.isMultisig()) {
m = redeem.getSmall(0);
n = redeem.getSmall(redeem.length - 2);
if (input.witness.length - 1 !== m + 1)
return false;
if (input.witness.get(0).length !== 0)
return false;
for (j = 1; j < input.witness.length - 1; j++) {
if (input.witness.get(i).length > 73)
return false;
}
}
}
return true;
};
/**
* Perform contextual checks to verify input, output,
* and fee values, as well as coinbase spend maturity

View File

@ -441,7 +441,11 @@ exports.script = {
MAX_MULTISIG_PUBKEYS: 20,
MAX_SCRIPTHASH_SIGOPS: 15,
MAX_OP_RETURN_BYTES: 83,
MAX_OP_RETURN: 80
MAX_OP_RETURN: 80,
BYTES_PER_SIGOP: 20,
MAX_P2WSH_STACK: 100,
MAX_P2WSH_PUSH: 80,
MAX_P2WSH_SIZE: 3600
};
/**