Skip to content
Permalink
Browse files

Merge #7387: Get rid of inaccurate ScriptSigArgsExpected

52b29dc Get rid of inaccurate ScriptSigArgsExpected (Pieter Wuille)
  • Loading branch information
laanwj committed Jan 22, 2016
2 parents 7726c48 + 52b29dc commit f4b2ce8ee8630789922a14cd9ee9037d96dba1b1
Showing with 6 additions and 70 deletions.
  1. +6 −31 src/policy/policy.cpp
  2. +0 −21 src/script/standard.cpp
  3. +0 −1 src/script/standard.h
  4. +0 −9 src/test/script_P2SH_tests.cpp
  5. +0 −8 src/test/transaction_tests.cpp
@@ -135,45 +135,20 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
const CScript& prevScript = prev.scriptPubKey;
if (!Solver(prevScript, whichType, vSolutions))
return false;
int nArgsExpected = ScriptSigArgsExpected(whichType, vSolutions);
if (nArgsExpected < 0)
return false;

// 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
// IsStandardTx() will have already returned false
// and this method isn't called.
std::vector<std::vector<unsigned char> > stack;
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker()))
return false;

if (whichType == TX_SCRIPTHASH)
{
std::vector<std::vector<unsigned char> > stack;
// convert the scriptSig into a stack, so we can inspect the redeemScript
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), 0))
return false;
if (stack.empty())
return false;
CScript subscript(stack.back().begin(), stack.back().end());
std::vector<std::vector<unsigned char> > vSolutions2;
txnouttype whichType2;
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 (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
return false;
}
}

if (stack.size() != (unsigned int)nArgsExpected)
return false;
}

return true;
@@ -161,27 +161,6 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
return false;
}

int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions)
{
switch (t)
{
case TX_NONSTANDARD:
case TX_NULL_DATA:
return -1;
case TX_PUBKEY:
return 1;
case TX_PUBKEYHASH:
return 2;
case TX_MULTISIG:
if (vSolutions.size() < 1 || vSolutions[0].size() < 1)
return -1;
return vSolutions[0][0] + 1;
case TX_SCRIPTHASH:
return 1; // doesn't include args needed by the script
}
return -1;
}

bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
{
vector<valtype> vSolutions;
@@ -71,7 +71,6 @@ typedef boost::variant<CNoDestination, CKeyID, CScriptID> CTxDestination;
const char* GetTxnOutputType(txnouttype t);

bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions);
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);

@@ -346,15 +346,6 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
// 22 P2SH sigops for all inputs (1 for vin[0], 6 for vin[3], 15 for vin[4]
BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txTo, coins), 22U);

// Make sure adding crap to the scriptSigs makes them non-standard:
for (int i = 0; i < 3; i++)
{
CScript t = txTo.vin[i].scriptSig;
txTo.vin[i].scriptSig = (CScript() << 11) + t;
BOOST_CHECK(!::AreInputsStandard(txTo, coins));
txTo.vin[i].scriptSig = t;
}

CMutableTransaction txToNonStd1;
txToNonStd1.vout.resize(1);
txToNonStd1.vout[0].scriptPubKey = GetScriptForDestination(key[1].GetPubKey().GetID());
@@ -310,14 +310,6 @@ BOOST_AUTO_TEST_CASE(test_Get)

BOOST_CHECK(AreInputsStandard(t1, coins));
BOOST_CHECK_EQUAL(coins.GetValueIn(t1), (50+21+22)*CENT);

// Adding extra junk to the scriptSig should make it non-standard:
t1.vin[0].scriptSig << OP_11;
BOOST_CHECK(!AreInputsStandard(t1, coins));

// ... as should not having enough:
t1.vin[0].scriptSig = CScript();
BOOST_CHECK(!AreInputsStandard(t1, coins));
}

BOOST_AUTO_TEST_CASE(test_IsStandard)

0 comments on commit f4b2ce8

Please sign in to comment.
You can’t perform that action at this time.