mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-19 06:43:45 +01:00
Relax IsStandard rules for pay-to-script-hash transactions
Relax the AreInputsStandard() tests for P2SH transactions -- allow any Script in a P2SH transaction to be relayed/mined, as long as it has 15 or fewer signature operations. Rationale: https://gist.github.com/gavinandresen/88be40c141bc67acb247 I don't have an easy way to test this, but the code changes are straightforward and I've updated the AreInputsStandard unit tests.
This commit is contained in:
43
src/main.cpp
43
src/main.cpp
@@ -582,15 +582,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)
|
||||
{
|
||||
@@ -614,8 +612,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;
|
||||
@@ -627,16 +626,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