Do not relay or mine excessive sighash transactions

This is a belt-and-suspenders fix to make sure CreateNewBlock() or external mining software can never produce a block that violates the MAX_BLOCK_SIGHASH rule.

It does this by rejecting transactions that do too much signature hashing -- they are not added to the memory pool, and so will not be considered for inclusion in new blocks.

How the code works: every transaction uses up some fraction of the MAX_BLOCK_SIZE limit and the MAX_BLOCK_SIGHASH limit. If a transaction uses up a larger fraction of the SIGHASH limit than the SIZE limit, it is rejected. That ensures that no matter which transactions are selected for the block, the SIZE limit will be hit before the SIGHASH limit.

This is a much simpler solution than modifying CreateNewBlock or external transaction selection software to keep track of the SIZE limit, the SIGOPS limit, AND the new SIGHASH limit.

This is belt-and-suspenders because, in practice, the 100,000-byte IsStandard size limit prevents the block SIGHASH limit from being hit.

The IsStandard code related to the old SIGOPS limit is left unchanged.

Conflicts:
	src/main.cpp
This commit is contained in:
Gavin Andresen
2016-02-02 13:55:21 -05:00
committed by Tom Zander
parent 3aadc515e0
commit 70d2aad340

View File

@@ -1183,8 +1183,22 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
if (!CheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, NULL))
ValidationCostTracker costTracker(MAX_BLOCK_SIGOPS, MAX_BLOCK_SIGHASH);
if (!CheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, &costTracker))
{
return false;
}
// Reject transactions with very high signature-hash cost:
uint64_t sighash_limit = (uint64_t)nSize * MAX_BLOCK_SIGHASH / MAX_BLOCK_SIZE;
if (costTracker.GetSighashBytes() > sighash_limit)
{
return state.DoS(0,
error("AcceptToMemoryPool: too much signature hashing %s: %d > %d",
hash.ToString(), costTracker.GetSighashBytes(), sighash_limit),
REJECT_NONSTANDARD, "bat-txns-too-many-sighash");
}
LogPrint("txcost", "txcost %s size: %d sigops: %d sighash: %d\n",
hash.ToString(), nSize, costTracker.GetSigOps(), costTracker.GetSighashBytes());
// Check again against just the consensus-critical mandatory script
// verification flags, in case of bugs in the standard flags that cause