aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2014-06-27 10:53:24 -0400
committerGavin Andresen <gavinandresen@gmail.com>2014-06-27 10:53:24 -0400
commit62599373883a66a958136f48ab0e2b826e3d5bf8 (patch)
tree6a4ba3c3f9e3815b4b5ad8c0b89d8a63869a4adf /src/main.cpp
parent4684c883bba5733576695676b8ac9ca7726784ea (diff)
parent7f3b4e95695d50a4970e6eb91faa956ab276f161 (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.cpp43
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)