From ab4abe8097c6b23ea8e43c768afa6d508000f19a Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Mon, 8 Aug 2016 04:00:32 +0000 Subject: [PATCH] Restore original bytespersigop as bytespersigopstrict Plus a bugfix to accurately count sigops for this purpose --- src/init.cpp | 1 + src/policy/policy.cpp | 1 + src/policy/policy.h | 2 ++ src/policy/settings.cpp | 1 + src/policy/settings.h | 1 + src/validation.cpp | 37 ++++++++++++++++++++++++++++++++++++- 6 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/init.cpp b/src/init.cpp index 369d919d23..aa56ec8aa9 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -580,6 +580,7 @@ void SetupServerArgs(ArgsManager& argsman) argsman.AddArg("-incrementalrelayfee=", strprintf("Fee rate (in %s/kvB) used to define cost of relay, used for mempool limiting and replacement policy. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY); argsman.AddArg("-dustrelayfee=", strprintf("Fee rate (in %s/kvB) used to define dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY); argsman.AddArg("-bytespersigop", strprintf("Equivalent bytes per sigop in transactions for relay and mining (default: %u)", DEFAULT_BYTES_PER_SIGOP), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); + argsman.AddArg("-bytespersigopstrict", strprintf("Minimum bytes per sigop in transactions we relay and mine (default: %u)", DEFAULT_BYTES_PER_SIGOP_STRICT), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); argsman.AddArg("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); argsman.AddArg("-datacarriersize", strprintf("Maximum size of data in data carrier transactions we relay and mine (default: %u)", MAX_OP_RETURN_RELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); argsman.AddArg("-mempoolfullrbf", strprintf("Accept transaction replace-by-fee without requiring replaceability signaling (default: %u)", DEFAULT_MEMPOOL_FULL_RBF), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp index 46a8e3aa8e..726355cf67 100644 --- a/src/policy/policy.cpp +++ b/src/policy/policy.cpp @@ -7,6 +7,7 @@ #include +#include #include #include #include diff --git a/src/policy/policy.h b/src/policy/policy.h index 7dd4205b74..5ca3266f77 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -36,6 +36,8 @@ static constexpr unsigned int MAX_STANDARD_TX_SIGOPS_COST{MAX_BLOCK_SIGOPS_COST/ static constexpr unsigned int DEFAULT_INCREMENTAL_RELAY_FEE{1000}; /** Default for -bytespersigop */ static constexpr unsigned int DEFAULT_BYTES_PER_SIGOP{20}; +/** Default for -bytespersigopstrict */ +static constexpr unsigned int DEFAULT_BYTES_PER_SIGOP_STRICT{20}; /** Default for -permitbaremultisig */ static constexpr bool DEFAULT_PERMIT_BAREMULTISIG{true}; /** The maximum number of witness stack items in a standard P2WSH script */ diff --git a/src/policy/settings.cpp b/src/policy/settings.cpp index 722b12acf5..6200b4bd30 100644 --- a/src/policy/settings.cpp +++ b/src/policy/settings.cpp @@ -8,3 +8,4 @@ #include unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP; +unsigned int nBytesPerSigOpStrict = DEFAULT_BYTES_PER_SIGOP_STRICT; diff --git a/src/policy/settings.h b/src/policy/settings.h index 145454b0dd..14fb9b769b 100644 --- a/src/policy/settings.h +++ b/src/policy/settings.h @@ -7,5 +7,6 @@ #define BITCOIN_POLICY_SETTINGS_H extern unsigned int nBytesPerSigOp; +extern unsigned int nBytesPerSigOpStrict; #endif // BITCOIN_POLICY_SETTINGS_H diff --git a/src/validation.cpp b/src/validation.cpp index b84dd3a5e5..114e531a88 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -260,6 +260,38 @@ bool CheckSequenceLocksAtTip(CBlockIndex* tip, // Returns the script flags which should be checked for a given block static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman); +/** Compute accurate total signature operation cost of a transaction. + * Not consensus-critical, since legacy sigops counting is always used in the protocol. + */ +int64_t GetAccurateTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags) +{ + if (tx.IsCoinBase()) { + return 0; + } + + unsigned int nSigOps = 0; + for (const auto& txin : tx.vin) { + nSigOps += txin.scriptSig.GetSigOpCount(false); + } + + if (flags & SCRIPT_VERIFY_P2SH) { + nSigOps += GetP2SHSigOpCount(tx, inputs); + } + + nSigOps *= WITNESS_SCALE_FACTOR; + + if (flags & SCRIPT_VERIFY_WITNESS) { + for (const auto& txin : tx.vin) { + const Coin& coin = inputs.AccessCoin(txin.prevout); + assert(!coin.IsSpent()); + const CTxOut &prevout = coin.out; + nSigOps += CountWitnessSigOps(txin.scriptSig, prevout.scriptPubKey, &txin.scriptWitness, flags); + } + } + + return nSigOps; +} + void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs) { @@ -860,9 +892,12 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) fSpendsCoinbase, nSigOpsCost, lock_points.value())); ws.m_vsize = entry->GetTxSize(); - if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST) + // To avoid rejecting low-sigop bare-multisig transactions, the sigops + // are counted a second time more accurately. + if ((nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST) || (nBytesPerSigOpStrict && GetAccurateTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS) > ws.m_vsize * WITNESS_SCALE_FACTOR / nBytesPerSigOpStrict)) { MaybeRejectDbg(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops", strprintf("%d", nSigOpsCost)); + } // No individual transactions are allowed below the min relay feerate and mempool min feerate except from // disconnected blocks and transactions in a package. Package transactions will be checked using