Merge pull request #3843
787ee0cCheck redeemScript size does not exceed 520 byte limit (Peter Todd)4d79098Increase IsStandard() scriptSig length (Peter Todd)f80cffaDo not trigger a DoS ban if SCRIPT_VERIFY_NULLDUMMY fails (Peter Todd)6380180Add rejection of non-null CHECKMULTISIG dummy values (Peter Todd)29c1749Let tx (in)valid tests use any SCRIPT_VERIFY flag (Peter Todd)68f7d1dCreate (MANDATORY|STANDARD)_SCRIPT_VERIFY_FLAGS constants (Peter Todd)
This commit is contained in:
38
src/main.cpp
38
src/main.cpp
@@ -515,10 +515,14 @@ bool IsStandardTx(const CTransaction& tx, string& reason)
|
||||
|
||||
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
||||
{
|
||||
// Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG
|
||||
// pay-to-script-hash, which is 3 ~80-byte signatures, 3
|
||||
// ~65-byte public keys, plus a few script ops.
|
||||
if (txin.scriptSig.size() > 500) {
|
||||
// Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
|
||||
// keys. (remember the 520 byte limit on redeemScript size) That works
|
||||
// out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)=1624
|
||||
// bytes of scriptSig, which we round off to 1650 bytes for some minor
|
||||
// future-proofing. That's also enough to spend a 20-of-20
|
||||
// CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
|
||||
// considered standard)
|
||||
if (txin.scriptSig.size() > 1650) {
|
||||
reason = "scriptsig-size";
|
||||
return false;
|
||||
}
|
||||
@@ -945,7 +949,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
||||
|
||||
// Check against previous transactions
|
||||
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
|
||||
if (!CheckInputs(tx, state, view, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC))
|
||||
if (!CheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS))
|
||||
{
|
||||
return error("AcceptToMemoryPool: : ConnectInputs failed %s", hash.ToString());
|
||||
}
|
||||
@@ -1588,14 +1592,26 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach
|
||||
pvChecks->push_back(CScriptCheck());
|
||||
check.swap(pvChecks->back());
|
||||
} else if (!check()) {
|
||||
if (flags & SCRIPT_VERIFY_STRICTENC) {
|
||||
// For now, check whether the failure was caused by non-canonical
|
||||
// encodings or not; if so, don't trigger DoS protection.
|
||||
CScriptCheck check(coins, tx, i, flags & (~SCRIPT_VERIFY_STRICTENC), 0);
|
||||
if (flags & STANDARD_NOT_MANDATORY_VERIFY_FLAGS) {
|
||||
// Check whether the failure was caused by a
|
||||
// non-mandatory script verification check, such as
|
||||
// non-standard DER encodings or non-null dummy
|
||||
// arguments; if so, don't trigger DoS protection to
|
||||
// avoid splitting the network between upgraded and
|
||||
// non-upgraded nodes.
|
||||
CScriptCheck check(coins, tx, i,
|
||||
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, 0);
|
||||
if (check())
|
||||
return state.Invalid(false, REJECT_NONSTANDARD, "non-canonical");
|
||||
return state.Invalid(false, REJECT_NONSTANDARD, "non-mandatory-script-verify-flag");
|
||||
}
|
||||
return state.DoS(100,false, REJECT_NONSTANDARD, "non-canonical");
|
||||
// Failures of other flags indicate a transaction that is
|
||||
// invalid in new blocks, e.g. a invalid P2SH. We DoS ban
|
||||
// such nodes as they are not following the protocol. That
|
||||
// said during an upgrade careful thought should be taken
|
||||
// as to the correct behavior - we may want to continue
|
||||
// peering with non-upgraded nodes even after a soft-fork
|
||||
// super-majority vote has passed.
|
||||
return state.DoS(100,false, REJECT_INVALID, "mandatory-script-verify-flag-failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user