diff --git a/src/main.cpp b/src/main.cpp index 73fbe53afb6..846646a4c5b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1047,6 +1047,34 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i return nSigOps; } +/** Compute accurate total signature operation cost of a transaction. */ +static int64_t GetAccurateTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags) +{ + int64_t nSigOps = 0; + BOOST_FOREACH(const CTxIn& txin, tx.vin) + { + nSigOps += txin.scriptSig.GetSigOpCount(true); + } + BOOST_FOREACH(const CTxOut& txout, tx.vout) + { + nSigOps += txout.scriptPubKey.GetSigOpCount(true); + } + nSigOps *= WITNESS_SCALE_FACTOR; + + if (tx.IsCoinBase()) + return nSigOps; + + if (flags & SCRIPT_VERIFY_P2SH) { + nSigOps += GetP2SHSigOpCount(tx, inputs) * WITNESS_SCALE_FACTOR; + } + + for (unsigned int i = 0; i < tx.vin.size(); i++) + { + const CTxOut &prevout = inputs.GetOutputFor(tx.vin[i]); + nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, i < tx.wit.vtxinwit.size() ? &tx.wit.vtxinwit[i].scriptWitness : NULL, flags); + } + return nSigOps; +} @@ -1296,7 +1324,11 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // itself can contain sigops MAX_STANDARD_TX_SIGOPS is less than // MAX_BLOCK_SIGOPS; we still consider this an invalid rather than // merely non-standard transaction. - if ((nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST) || (nBytesPerSigOp && nSigOpsCost > nSize * WITNESS_SCALE_FACTOR / nBytesPerSigOp)) + // To avoid making certain bare-multisig transactions non-standard, + // the sigops are counted a second time + int64_t nAccurateSigOpsCost = GetAccurateTransactionSigOpCost(tx, view, STANDARD_SCRIPT_VERIFY_FLAGS); + + if ((nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST) || (nBytesPerSigOp && nAccurateSigOpsCost > nSize * WITNESS_SCALE_FACTOR / nBytesPerSigOp)) return state.DoS(0, false, REJECT_NONSTANDARD, "bad-txns-too-many-sigops", false, strprintf("%d", nSigOpsCost));