Skip to content

Commit cbecc46

Browse files
committed
Restore original bytespersigop as bytespersigopstrict
Plus a bugfix to accurately count sigops for this purpose
1 parent b63bf02 commit cbecc46

File tree

5 files changed

+42
-1
lines changed

5 files changed

+42
-1
lines changed

src/init.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,7 @@ void SetupServerArgs(ArgsManager& argsman)
642642
argsman.AddArg("-dustrelayfee=<amt>", 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);
643643
argsman.AddArg("-acceptstalefeeestimates", strprintf("Read fee estimates even if they are stale (%sdefault: %u) fee estimates are considered stale if they are %s hours old", "regtest only; ", DEFAULT_ACCEPT_STALE_FEE_ESTIMATES, Ticks<std::chrono::hours>(MAX_FILE_AGE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
644644
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);
645+
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);
645646
argsman.AddArg("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
646647
argsman.AddArg("-datacarriersize",
647648
strprintf("Relay and mine transactions whose data-carrying raw scriptPubKey "
@@ -1037,6 +1038,7 @@ bool AppInitParameterInteraction(const ArgsManager& args)
10371038
}
10381039

10391040
nBytesPerSigOp = args.GetIntArg("-bytespersigop", nBytesPerSigOp);
1041+
nBytesPerSigOpStrict = args.GetIntArg("-bytespersigopstrict", nBytesPerSigOpStrict);
10401042

10411043
if (!g_wallet_init_interface.ParameterInteraction()) return false;
10421044

src/policy/policy.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ static constexpr unsigned int MAX_STANDARD_TX_SIGOPS_COST{MAX_BLOCK_SIGOPS_COST/
3939
static constexpr unsigned int DEFAULT_INCREMENTAL_RELAY_FEE{1000};
4040
/** Default for -bytespersigop */
4141
static constexpr unsigned int DEFAULT_BYTES_PER_SIGOP{20};
42+
/** Default for -bytespersigopstrict */
43+
static constexpr unsigned int DEFAULT_BYTES_PER_SIGOP_STRICT{20};
4244
/** Default for -permitbarepubkey */
4345
static constexpr bool DEFAULT_PERMIT_BAREPUBKEY{true};
4446
/** Default for -permitbaremultisig */

src/policy/settings.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@
88
#include <policy/policy.h>
99

1010
unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
11+
unsigned int nBytesPerSigOpStrict = DEFAULT_BYTES_PER_SIGOP_STRICT;

src/policy/settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77
#define BITCOIN_POLICY_SETTINGS_H
88

99
extern unsigned int nBytesPerSigOp;
10+
extern unsigned int nBytesPerSigOpStrict;
1011

1112
#endif // BITCOIN_POLICY_SETTINGS_H

src/validation.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,38 @@ bool CheckSequenceLocksAtTip(CBlockIndex* tip,
263263
// Returns the script flags which should be checked for a given block
264264
static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman);
265265

266+
/** Compute accurate total signature operation cost of a transaction.
267+
* Not consensus-critical, since legacy sigops counting is always used in the protocol.
268+
*/
269+
int64_t GetAccurateTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags)
270+
{
271+
if (tx.IsCoinBase()) {
272+
return 0;
273+
}
274+
275+
unsigned int nSigOps = 0;
276+
for (const auto& txin : tx.vin) {
277+
nSigOps += txin.scriptSig.GetSigOpCount(false);
278+
}
279+
280+
if (flags & SCRIPT_VERIFY_P2SH) {
281+
nSigOps += GetP2SHSigOpCount(tx, inputs);
282+
}
283+
284+
nSigOps *= WITNESS_SCALE_FACTOR;
285+
286+
if (flags & SCRIPT_VERIFY_WITNESS) {
287+
for (const auto& txin : tx.vin) {
288+
const Coin& coin = inputs.AccessCoin(txin.prevout);
289+
assert(!coin.IsSpent());
290+
const CTxOut &prevout = coin.out;
291+
nSigOps += CountWitnessSigOps(txin.scriptSig, prevout.scriptPubKey, &txin.scriptWitness, flags);
292+
}
293+
}
294+
295+
return nSigOps;
296+
}
297+
266298
void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache)
267299
EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs)
268300
{
@@ -964,9 +996,12 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
964996
fSpendsCoinbase, nSigOpsCost, lock_points.value()));
965997
ws.m_vsize = entry->GetTxSize();
966998

967-
if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)
999+
// To avoid rejecting low-sigop bare-multisig transactions, the sigops
1000+
// are counted a second time more accurately.
1001+
if ((nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST) || (nBytesPerSigOpStrict && GetAccurateTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS) > ws.m_vsize * WITNESS_SCALE_FACTOR / nBytesPerSigOpStrict)) {
9681002
MaybeRejectDbg(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
9691003
strprintf("%d", nSigOpsCost));
1004+
}
9701005

9711006
// No individual transactions are allowed below the min relay feerate except from disconnected blocks.
9721007
// This requirement, unlike CheckFeeRate, cannot be bypassed using m_package_feerates because,

0 commit comments

Comments
 (0)