mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-18 22:35:39 +01:00
Merge pull request #4365 from gavinandresen/relax_isstandard
Relax IsStandard rules for pay-to-script-hash transactions
This commit is contained in:
43
src/main.cpp
43
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)
|
||||
|
||||
Reference in New Issue
Block a user