diff options
author | Gavin Andresen <gavinandresen@gmail.com> | 2014-06-27 10:53:24 -0400 |
---|---|---|
committer | Gavin Andresen <gavinandresen@gmail.com> | 2014-06-27 10:53:24 -0400 |
commit | 62599373883a66a958136f48ab0e2b826e3d5bf8 (patch) | |
tree | 6a4ba3c3f9e3815b4b5ad8c0b89d8a63869a4adf /src/main.cpp | |
parent | 4684c883bba5733576695676b8ac9ca7726784ea (diff) | |
parent | 7f3b4e95695d50a4970e6eb91faa956ab276f161 (diff) |
Merge pull request #4365 from gavinandresen/relax_isstandard
Relax IsStandard rules for pay-to-script-hash transactions
Diffstat (limited to 'src/main.cpp')
-rw-r--r-- | src/main.cpp | 43 |
1 files changed, 23 insertions, 20 deletions
diff --git a/src/main.cpp b/src/main.cpp index e06c519ee2..d86fd3a24d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -583,15 +583,13 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime) } // -// Check transaction inputs, and make sure any -// pay-to-script-hash transactions are evaluating IsStandard scripts +// Check transaction inputs to mitigate two +// potential denial-of-service attacks: // -// Why bother? To avoid denial-of-service attacks; an attacker -// can submit a standard HASH... OP_EQUAL transaction, -// which will get accepted into blocks. The redemption -// script can be anything; an attacker could use a very -// expensive-to-check-upon-redemption script like: -// DUP CHECKSIG DROP ... repeated 100 times... OP_1 +// 1. scriptSigs with extra data stuffed into them, +// not consumed by scriptPubKey (or P2SH script) +// 2. P2SH scripts with a crazy number of expensive +// CHECKSIG/CHECKMULTISIG operations // bool AreInputsStandard(const CTransaction& tx, CCoinsViewCache& mapInputs) { @@ -615,8 +613,9 @@ bool AreInputsStandard(const CTransaction& tx, CCoinsViewCache& mapInputs) // Transactions with extra stuff in their scriptSigs are // non-standard. Note that this EvalScript() call will // be quick, because if there are any operations - // beside "push data" in the scriptSig the - // IsStandard() call returns false + // beside "push data" in the scriptSig + // IsStandard() will have already returned false + // and this method isn't called. vector<vector<unsigned char> > stack; if (!EvalScript(stack, tx.vin[i].scriptSig, tx, i, false, 0)) return false; @@ -628,16 +627,20 @@ bool AreInputsStandard(const CTransaction& tx, CCoinsViewCache& mapInputs) CScript subscript(stack.back().begin(), stack.back().end()); vector<vector<unsigned char> > vSolutions2; txnouttype whichType2; - if (!Solver(subscript, whichType2, vSolutions2)) - return false; - if (whichType2 == TX_SCRIPTHASH) - return false; - - int tmpExpected; - tmpExpected = ScriptSigArgsExpected(whichType2, vSolutions2); - if (tmpExpected < 0) - return false; - nArgsExpected += tmpExpected; + if (Solver(subscript, whichType2, vSolutions2)) + { + int tmpExpected = ScriptSigArgsExpected(whichType2, vSolutions2); + if (tmpExpected < 0) + return false; + nArgsExpected += tmpExpected; + } + else + { + // Any other Script with less than 15 sigops OK: + unsigned int sigops = subscript.GetSigOpCount(true); + // ... extra data left on the stack after execution is OK, too: + return (sigops <= MAX_P2SH_SIGOPS); + } } if (stack.size() != (unsigned int)nArgsExpected) |