diff --git a/src/miner.cpp b/src/miner.cpp --- a/src/miner.cpp +++ b/src/miner.cpp @@ -212,8 +212,8 @@ UpdateTime(pblock, *config, pindexPrev); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, *config); pblock->nNonce = 0; - pblocktemplate->vTxSigOpsCount[0] = - GetSigOpCountWithoutP2SH(*pblock->vtx[0]); + pblocktemplate->vTxSigOpsCount[0] = GetSigOpCountWithoutP2SH( + *pblock->vtx[0], STANDARD_CHECKDATASIG_VERIFY_FLAGS); CValidationState state; BlockValidationOptions validationOptions(false, false); diff --git a/src/policy/policy.h b/src/policy/policy.h --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -88,6 +88,14 @@ static const uint32_t STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_VERIFY_SEQUENCE | LOCKTIME_MEDIAN_TIME_PAST; +/** + * Used as the flags parameters to check for sigops as if OP_CHECKDATASIG is + * enabled. Can be removed after OP_CHECKDATASIG is activated as the flag is + * made standard. + */ +static const uint32_t STANDARD_CHECKDATASIG_VERIFY_FLAGS = + STANDARD_SCRIPT_VERIFY_FLAGS | SCRIPT_ENABLE_CHECKDATASIG; + bool IsStandard(const CScript &scriptPubKey, txnouttype &whichType); /** diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -413,7 +413,12 @@ BOOST_CHECK(::AreInputsStandard(CTransaction(txTo), coins)); // 22 P2SH sigops for all inputs (1 for vin[0], 6 for vin[3], 15 for vin[4] - BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txTo), coins), 22U); + BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txTo), coins, + STANDARD_CHECKDATASIG_VERIFY_FLAGS), + 22U); + // Check that no sigops show up when P2SH is not activated. + BOOST_CHECK_EQUAL( + GetP2SHSigOpCount(CTransaction(txTo), coins, SCRIPT_VERIFY_NONE), 0); CMutableTransaction txToNonStd1; txToNonStd1.vout.resize(1); @@ -426,7 +431,13 @@ << std::vector(sixteenSigops.begin(), sixteenSigops.end()); BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd1), coins)); - BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd1), coins), 16U); + BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd1), coins, + STANDARD_CHECKDATASIG_VERIFY_FLAGS), + 16U); + // Check that no sigops show up when P2SH is not activated. + BOOST_CHECK_EQUAL( + GetP2SHSigOpCount(CTransaction(txToNonStd1), coins, SCRIPT_VERIFY_NONE), + 0); CMutableTransaction txToNonStd2; txToNonStd2.vout.resize(1); @@ -439,7 +450,13 @@ << std::vector(twentySigops.begin(), twentySigops.end()); BOOST_CHECK(!::AreInputsStandard(CTransaction(txToNonStd2), coins)); - BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd2), coins), 20U); + BOOST_CHECK_EQUAL(GetP2SHSigOpCount(CTransaction(txToNonStd2), coins, + STANDARD_CHECKDATASIG_VERIFY_FLAGS), + 20U); + // Check that no sigops show up when P2SH is not activated. + BOOST_CHECK_EQUAL( + GetP2SHSigOpCount(CTransaction(txToNonStd2), coins, SCRIPT_VERIFY_NONE), + 0); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/validation.h b/src/validation.h --- a/src/validation.h +++ b/src/validation.h @@ -464,7 +464,7 @@ * @return number of sigops this transaction's outputs will produce when spent * @see CTransaction::FetchInputs */ -uint64_t GetSigOpCountWithoutP2SH(const CTransaction &tx); +uint64_t GetSigOpCountWithoutP2SH(const CTransaction &tx, uint32_t flags); /** * Count ECDSA signature operations in pay-to-script-hash inputs. @@ -476,18 +476,19 @@ * @see CTransaction::FetchInputs */ uint64_t GetP2SHSigOpCount(const CTransaction &tx, - const CCoinsViewCache &mapInputs); + const CCoinsViewCache &mapInputs, uint32_t flags); /** * Compute total signature operation of a transaction. * @param[in] tx Transaction for which we are computing the cost * @param[in] inputs Map of previous transactions that have outputs we're * spending - * @param[out] flags Script verification flags + * @param[in] flags Script verification flags * @return Total signature operation cost of tx */ uint64_t GetTransactionSigOpCount(const CTransaction &tx, - const CCoinsViewCache &inputs, int flags); + const CCoinsViewCache &inputs, + uint32_t flags); /** * Check whether all inputs of this transaction are valid (no double spends, @@ -523,8 +524,10 @@ /** Transaction validation functions */ -/** Context-independent validity checks for coinbase and non-coinbase - * transactions */ +/** + * Context-independent validity checks for coinbase and non-coinbase + * transactions. + */ bool CheckRegularTransaction(const CTransaction &tx, CValidationState &state, bool fCheckDuplicateInputs = true); bool CheckCoinbase(const CTransaction &tx, CValidationState &state, diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -381,7 +381,7 @@ return EvaluateSequenceLocks(index, lockPair); } -uint64_t GetSigOpCountWithoutP2SH(const CTransaction &tx) { +uint64_t GetSigOpCountWithoutP2SH(const CTransaction &tx, uint32_t flags) { uint64_t nSigOps = 0; for (const auto &txin : tx.vin) { nSigOps += txin.scriptSig.GetSigOpCount(false); @@ -392,9 +392,9 @@ return nSigOps; } -uint64_t GetP2SHSigOpCount(const CTransaction &tx, - const CCoinsViewCache &view) { - if (tx.IsCoinBase()) { +uint64_t GetP2SHSigOpCount(const CTransaction &tx, const CCoinsViewCache &view, + uint32_t flags) { + if ((flags & SCRIPT_VERIFY_P2SH) == 0 || tx.IsCoinBase()) { return 0; } @@ -405,21 +405,14 @@ nSigOps += prevout.scriptPubKey.GetSigOpCount(i.scriptSig); } } + return nSigOps; } uint64_t GetTransactionSigOpCount(const CTransaction &tx, - const CCoinsViewCache &view, int flags) { - uint64_t nSigOps = GetSigOpCountWithoutP2SH(tx); - if (tx.IsCoinBase()) { - return nSigOps; - } - - if (flags & SCRIPT_VERIFY_P2SH) { - nSigOps += GetP2SHSigOpCount(tx, view); - } - - return nSigOps; + const CCoinsViewCache &view, uint32_t flags) { + return GetSigOpCountWithoutP2SH(tx, flags) + + GetP2SHSigOpCount(tx, view, flags); } static bool CheckTransactionCommon(const CTransaction &tx, @@ -459,7 +452,8 @@ } } - if (GetSigOpCountWithoutP2SH(tx) > MAX_TX_SIGOPS_COUNT) { + if (GetSigOpCountWithoutP2SH(tx, STANDARD_CHECKDATASIG_VERIFY_FLAGS) > + MAX_TX_SIGOPS_COUNT) { return state.DoS(100, false, REJECT_INVALID, "bad-txn-sigops"); } @@ -2118,7 +2112,7 @@ if (tx.IsCoinBase()) { // We've already checked for sigops count before P2SH in CheckBlock. - nSigOpsCount += GetSigOpCountWithoutP2SH(tx); + nSigOpsCount += GetSigOpCountWithoutP2SH(tx, flags); } if (fIsMagneticAnomalyEnabled || tx.IsCoinBase()) { @@ -3507,7 +3501,7 @@ while (true) { // Count the sigops for the current transaction. If the total sigops // count is too high, the the block is invalid. - nSigOps += GetSigOpCountWithoutP2SH(*tx); + nSigOps += GetSigOpCountWithoutP2SH(*tx, STANDARD_SCRIPT_VERIFY_FLAGS); if (nSigOps > nMaxSigOpsCount) { return state.DoS(100, false, REJECT_INVALID, "bad-blk-sigops", false, "out-of-bounds SigOpCount");