Skip to content
Bitcoin Roots

v30.3-roots.1 · Commit 3: [PATCH 03/68] feat(policy): preserve Roots relay and network controls on Core 30.3

src/validation.cpp

Before: src/validation.cpp · After: src/validation.cpp

File metadata
index 21ccf045fbfcd200ec1dea6ad867a65eec02dfbc..89daf215e6c9aec6905aa611c1c360fc980e9921 100644

Download original patch · Release notes

Diff rows 401–800 of 802. Line numbers refer to the original before/after files.

+ Added− RemovedUnmarked lines are context.

Scroll the code area horizontally to read long lines. Before is on the left; after is on the right. Unified view fits narrow screens more easily.

src/validation.cpp CHANGED
@@ -926,29 +1079,63 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) (continued)
 
 
 
 
 
 
 
 
 
942
  // Enforces 0-fee for dust transactions, no incentive to be mined alone
943
- if (m_pool.m_opts.require_standard) {
944
  if (!PreCheckEphemeralTx(*ptx, m_pool.m_opts.dust_relay_feerate, ws.m_base_fees, ws.m_modified_fees, state)) {
945
  return false; // state filled in by PreCheckEphemeralTx
946
  }
947
  }
948
 
949
- if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)
950
- return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
 
 
951
  strprintf("%d", nSigOpsCost));
 
952
 
953
  // No individual transactions are allowed below the min relay feerate except from disconnected blocks.
954
  // This requirement, unlike CheckFeeRate, cannot be bypassed using m_package_feerates because,
@@ -956,7 +1143,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
956
  // method of ensuring the tx remains bumped. For example, the fee-bumping child could disappear
957
  // due to a replacement.
958
  // The only exception is TRUC transactions.
959
- if (!bypass_limits && ws.m_ptx->version != TRUC_VERSION && ws.m_modified_fees < m_pool.m_opts.min_relay_feerate.GetFee(ws.m_vsize)) {
960
  // Even though this is a fee-related failure, this result is TX_MEMPOOL_POLICY, not
961
  // TX_RECONSIDERABLE, because it cannot be bypassed using package validation.
962
  return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met",
@@ -965,16 +1152,20 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
965
  // No individual transactions are allowed below the mempool min feerate except from disconnected
966
  // blocks and transactions in a package. Package transactions will be checked using package
967
  // feerate later.
968
- if (!bypass_limits && !args.m_package_feerates && !CheckFeeRate(ws.m_vsize, ws.m_modified_fees, state)) return false;
969
 
970
- ws.m_iters_conflicting = m_pool.GetIterSet(ws.m_conflicts);
 
 
 
 
971
 
972
  // Note that these modifications are only applicable to single transaction scenarios;
973
  // carve-outs are disabled for multi-transaction evaluations.
974
  CTxMemPool::Limits maybe_rbf_limits = m_pool.m_opts.limits;
975
 
976
  // Calculate in-mempool ancestors, up to a limit.
977
- if (ws.m_conflicts.size() == 1 && args.m_allow_carveouts) {
978
  // In general, when we receive an RBF transaction with mempool conflicts, we want to know whether we
979
  // would meet the chain limits after the conflicts have been removed. However, there isn't a practical
980
  // way to do this short of calculating the ancestor and descendant sets with an overlay cache of
@@ -1009,7 +1200,13 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
1009
  maybe_rbf_limits.descendant_size_vbytes += conflict->GetSizeWithDescendants();
1010
  }
1011
 
1012
- if (auto ancestors{m_subpackage.m_changeset->CalculateMemPoolAncestors(ws.m_tx_handle, maybe_rbf_limits)}) {
 
 
 
 
 
 
1013
  ws.m_ancestors = std::move(*ancestors);
1014
  } else {
1015
  // If CalculateMemPoolAncestors fails second time, we want the original error string.
@@ -1038,7 +1235,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
1038
  .descendant_count = maybe_rbf_limits.descendant_count + 1,
1039
  .descendant_size_vbytes = maybe_rbf_limits.descendant_size_vbytes + EXTRA_DESCENDANT_TX_SIZE_LIMIT,
1040
  };
1041
- if (ws.m_vsize > EXTRA_DESCENDANT_TX_SIZE_LIMIT || ws.m_ptx->version == TRUC_VERSION) {
1042
  return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too-long-mempool-chain", error_message);
1043
  }
1044
  if (auto ancestors_retry{m_subpackage.m_changeset->CalculateMemPoolAncestors(ws.m_tx_handle, cpfp_carve_out_limits)}) {
@@ -1051,8 +1248,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
1051
  // Even though just checking direct mempool parents for inheritance would be sufficient, we
1052
  // check using the full ancestor set here because it's more convenient to use what we have
1053
  // already calculated.
1054
- if (!args.m_bypass_limits) {
1055
- if (const auto err{SingleTRUCChecks(ws.m_ptx, ws.m_ancestors, ws.m_conflicts, ws.m_vsize)}) {
1056
  // Single transaction contexts only.
1057
  if (args.m_allow_sibling_eviction && err->second != nullptr) {
1058
  // We should only be considering where replacement is considered valid as well.
@@ -1060,7 +1257,8 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
1060
 
1061
  // Potential sibling eviction. Add the sibling to our list of mempool conflicts to be
1062
  // included in RBF checks.
1063
- ws.m_conflicts.insert(err->second->GetHash());
 
1064
  // Adding the sibling to m_iters_conflicting here means that it doesn't count towards
1065
  // RBF Carve Out above. This is correct, since removing to-be-replaced transactions from
1066
  // the descendant count is done separately in SingleTRUCChecks for TRUC transactions.
@@ -1071,7 +1269,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
1071
  // (which is normally done in PreChecks). However, the only way a TRUC transaction can
1072
  // have a non-TRUC and non-BIP125 descendant is due to a reorg.
1073
  } else {
1074
- return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "TRUC-violation", err->first);
1075
  }
1076
  }
1077
  }
@@ -1080,18 +1278,22 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
1080
  // that we have the set of all ancestors we can detect this
1081
  // pathological case by making sure ws.m_conflicts and ws.m_ancestors don't
1082
  // intersect.
1083
- if (const auto err_string{EntriesAndTxidsDisjoint(ws.m_ancestors, ws.m_conflicts, hash)}) {
 
1084
  // We classify this as a consensus error because a transaction depending on something it
1085
  // conflicts with would be inconsistent.
1086
  return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-spends-conflicting-tx", *err_string);
1087
  }
 
 
 
1088
 
1089
  // We want to detect conflicts in any tx in a package to trigger package RBF logic
1090
- m_subpackage.m_rbf |= !ws.m_conflicts.empty();
1091
  return true;
1092
  }
1093
 
1094
- bool MemPoolAccept::ReplacementChecks(Workspace& ws)
1095
  {
1096
  AssertLockHeld(cs_main);
1097
  AssertLockHeld(m_pool.cs);
@@ -1110,27 +1312,31 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
1110
  // guarantee that this is incentive-compatible for miners, because it is possible for a
1111
  // descendant transaction of a direct conflict to pay a higher feerate than the transaction that
1112
  // might replace them, under these rules.
 
1113
  if (const auto err_string{PaysMoreThanConflicts(ws.m_iters_conflicting, newFeeRate, hash)}) {
1114
  // This fee-related failure is TX_RECONSIDERABLE because validating in a package may change
1115
  // the result.
1116
  return state.Invalid(TxValidationResult::TX_RECONSIDERABLE,
1117
  strprintf("insufficient fee%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
1118
  }
 
1119
 
1120
  CTxMemPool::setEntries all_conflicts;
1121
 
1122
  // Calculate all conflicting entries and enforce Rule #5.
1123
- if (const auto err_string{GetEntriesForConflicts(tx, m_pool, ws.m_iters_conflicting, all_conflicts)}) {
1124
  return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
1125
  strprintf("too many potential replacements%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
1126
  }
1127
  // Enforce Rule #2.
 
1128
  if (const auto err_string{HasNoNewUnconfirmed(tx, m_pool, all_conflicts)}) {
1129
  // Sibling eviction is only done for TRUC transactions, which cannot have multiple ancestors.
1130
  Assume(!ws.m_sibling_eviction);
1131
  return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
1132
  strprintf("replacement-adds-unconfirmed%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
1133
  }
 
1134
 
1135
  // Check if it's economically rational to mine this transaction rather than the ones it
1136
  // replaces and pays for its own relay fees. Enforce Rules #3 and #4.
@@ -1138,12 +1344,14 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
1138
  m_subpackage.m_conflicting_fees += it->GetModifiedFee();
1139
  m_subpackage.m_conflicting_size += it->GetTxSize();
1140
  }
 
1141
  if (const auto err_string{PaysForRBF(m_subpackage.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
1142
  m_pool.m_opts.incremental_relay_feerate, hash)}) {
1143
  // Result may change in a package context
1144
  return state.Invalid(TxValidationResult::TX_RECONSIDERABLE,
1145
  strprintf("insufficient fee%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
1146
  }
 
1147
 
1148
  // Add all the to-be-removed transactions to the changeset.
1149
  for (auto it : all_conflicts) {
@@ -1152,7 +1360,7 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
1152
  return true;
1153
  }
1154
 
1155
- bool MemPoolAccept::PackageMempoolChecks(const std::vector<CTransactionRef>& txns,
1156
  std::vector<Workspace>& workspaces,
1157
  const int64_t total_vsize,
1158
  PackageValidationState& package_state)
@@ -1165,7 +1373,13 @@ bool MemPoolAccept::PackageMempoolChecks(const std::vector<CTransactionRef>& txn
1165
 
1166
  assert(txns.size() == workspaces.size());
1167
 
1168
- auto result = m_pool.CheckPackageLimits(txns, total_vsize);
 
 
 
 
 
 
1169
  if (!result) {
1170
  // This is a package-wide error, separate from an individual transaction error.
1171
  return package_state.Invalid(PackageValidationResult::PCKG_POLICY, "package-mempool-limits", util::ErrorString(result).original);
@@ -1251,6 +1465,77 @@ bool MemPoolAccept::PackageMempoolChecks(const std::vector<CTransactionRef>& txn
1251
  return true;
1252
  }
1253
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1254
  bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
1255
  {
1256
  AssertLockHeld(cs_main);
@@ -1258,7 +1543,7 @@ bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
1258
  const CTransaction& tx = *ws.m_ptx;
1259
  TxValidationState& state = ws.m_state;
1260
 
1261
- constexpr unsigned int scriptVerifyFlags = STANDARD_SCRIPT_VERIFY_FLAGS;
1262
 
1263
  // Check input scripts and signatures.
1264
  // This is done last to help prevent CPU exhaustion denial-of-service attacks.
@@ -1300,7 +1585,7 @@ bool MemPoolAccept::ConsensusScriptChecks(const ATMPArgs& args, Workspace& ws)
1300
  unsigned int currentBlockScriptVerifyFlags{GetBlockScriptFlags(*m_active_chainstate.m_chain.Tip(), m_active_chainstate.m_chainman)};
1301
  if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags,
1302
  ws.m_precomputed_txdata, m_active_chainstate.CoinsTip(), GetValidationCache())) {
1303
- LogPrintf("BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s\n", hash.ToString(), state.ToString());
1304
  return Assume(false);
1305
  }
1306
 
@@ -1425,7 +1710,7 @@ bool MemPoolAccept::SubmitPackage(const ATMPArgs& args, std::vector<Workspace>&
1425
  const CTransaction& tx = *ws.m_ptx;
1426
  const auto tx_info = NewMempoolTransactionInfo(ws.m_ptx, ws.m_base_fees,
1427
  ws.m_vsize, (*iter)->GetHeight(),
1428
- args.m_bypass_limits, args.m_package_submission,
1429
  IsCurrentForFeeEstimation(m_active_chainstate),
1430
  m_pool.HasNoInputsOf(tx));
1431
  m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());
@@ -1465,7 +1750,7 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
1465
  }
1466
  }
1467
 
1468
- if (m_subpackage.m_rbf && !ReplacementChecks(ws)) {
1469
  if (ws.m_state.GetResult() == TxValidationResult::TX_RECONSIDERABLE) {
1470
  // Failed for incentives-based fee reasons. Provide the effective feerate and which tx was included.
1471
  return MempoolAcceptResult::FeeFailure(ws.m_state, CFeeRate(ws.m_modified_fees, ws.m_vsize), single_wtxid);
@@ -1489,7 +1774,7 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
1489
  FinalizeSubpackage(args);
1490
 
1491
  // Limit the mempool, if appropriate.
1492
- if (!args.m_package_submission && !args.m_bypass_limits) {
1493
  LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip());
1494
  // If mempool contents change, then the m_view cache is dirty. Given this isn't a package
1495
  // submission, we won't be using the cache anymore, but clear it anyway for clarity.
@@ -1508,7 +1793,7 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
1508
  Assume(iter.has_value());
1509
  const auto tx_info = NewMempoolTransactionInfo(ws.m_ptx, ws.m_base_fees,
1510
  ws.m_vsize, (*iter)->GetHeight(),
1511
- args.m_bypass_limits, args.m_package_submission,
1512
  IsCurrentForFeeEstimation(m_active_chainstate),
1513
  m_pool.HasNoInputsOf(tx));
1514
  m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());
@@ -1575,12 +1860,14 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
1575
 
1576
  // At this point we have all in-mempool ancestors, and we know every transaction's vsize.
1577
  // Run the TRUC checks on the package.
 
 
1578
  for (Workspace& ws : workspaces) {
1579
- if (auto err{PackageTRUCChecks(ws.m_ptx, ws.m_vsize, txns, ws.m_ancestors)}) {
1580
- package_state.Invalid(PackageValidationResult::PCKG_POLICY, "TRUC-violation", err.value());
1581
  return PackageMempoolAcceptResult(package_state, {});
1582
  }
1583
- }
1584
 
1585
  // Transactions must meet two minimum feerates: the mempool minimum fee and min relay fee.
1586
  // For transactions consisting of exactly one child and its parents, it suffices to use the
@@ -1602,7 +1889,8 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
1602
  [](const auto& ws) { return ws.m_ptx->GetWitnessHash(); });
1603
  TxValidationState placeholder_state;
1604
  if (args.m_package_feerates &&
1605
- !CheckFeeRate(m_subpackage.m_total_vsize, m_subpackage.m_total_modified_fees, placeholder_state)) {
 
1606
  package_state.Invalid(PackageValidationResult::PCKG_TX, "transaction failed");
1607
  return PackageMempoolAcceptResult(package_state, {{workspaces.back().m_ptx->GetWitnessHash(),
1608
  MempoolAcceptResult::FeeFailure(placeholder_state, CFeeRate(m_subpackage.m_total_modified_fees, m_subpackage.m_total_vsize), all_package_wtxids)}});
@@ -1610,12 +1898,12 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
1610
 
1611
  // Apply package mempool ancestor/descendant limits. Skip if there is only one transaction,
1612
  // because it's unnecessary.
1613
- if (txns.size() > 1 && !PackageMempoolChecks(txns, workspaces, m_subpackage.m_total_vsize, package_state)) {
1614
  return PackageMempoolAcceptResult(package_state, std::move(results));
1615
  }
1616
 
1617
  // Now that we've bounded the resulting possible ancestry count, check package for dust spends
1618
- if (m_pool.m_opts.require_standard) {
1619
  TxValidationState child_state;
1620
  Wtxid child_wtxid;
1621
  if (!CheckEphemeralSpends(txns, m_pool.m_opts.dust_relay_feerate, m_pool, child_state, child_wtxid)) {
@@ -1865,7 +2153,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
1865
  } // anon namespace
1866
 
1867
  MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTransactionRef& tx,
1868
- int64_t accept_time, bool bypass_limits, bool test_accept)
1869
  {
1870
  AssertLockHeld(::cs_main);
1871
  const CChainParams& chainparams{active_chainstate.m_chainman.GetParams()};
@@ -1873,7 +2161,7 @@ MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTra
1873
  CTxMemPool& pool{*active_chainstate.GetMempool()};
1874
 
1875
  std::vector<COutPoint> coins_to_uncache;
1876
- auto args = MemPoolAccept::ATMPArgs::SingleAccept(chainparams, accept_time, bypass_limits, coins_to_uncache, test_accept);
1877
  MempoolAcceptResult result = MemPoolAccept(pool, active_chainstate).AcceptSingleTransaction(tx, args);
1878
  if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
1879
  // Remove coins that were not present in the coins cache before calling
@@ -1895,7 +2183,7 @@ MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTra
1895
  }
1896
 
1897
  PackageMempoolAcceptResult ProcessNewPackage(Chainstate& active_chainstate, CTxMemPool& pool,
1898
- const Package& package, bool test_accept, const std::optional<CFeeRate>& client_maxfeerate)
1899
  {
1900
  AssertLockHeld(cs_main);
1901
  assert(!package.empty());
@@ -1906,10 +2194,10 @@ PackageMempoolAcceptResult ProcessNewPackage(Chainstate& active_chainstate, CTxM
1906
  auto result = [&]() EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
1907
  AssertLockHeld(cs_main);
1908
  if (test_accept) {
1909
- auto args = MemPoolAccept::ATMPArgs::PackageTestAccept(chainparams, GetTime(), coins_to_uncache);
1910
  return MemPoolAccept(pool, active_chainstate).AcceptMultipleTransactions(package, args);
1911
  } else {
1912
- auto args = MemPoolAccept::ATMPArgs::PackageChildWithParents(chainparams, GetTime(), coins_to_uncache, client_maxfeerate);
1913
  return MemPoolAccept(pool, active_chainstate).AcceptPackage(package, args);
 
1117
+ }
1118
+ if (dust_penalty > 0) {
1119
+ m_subpackage.m_changeset->m_to_add.modify(ws.m_tx_handle, [&](CTxMemPoolEntry& e) {
1120
+ e.UpdateModifiedFee(-dust_penalty);
1121
+ });
1122
+ ws.m_modified_fees = SaturatingAdd(ws.m_modified_fees, -dust_penalty);
1123
+ }
1124
+ }
1125
+
1126
  // Enforces 0-fee for dust transactions, no incentive to be mined alone
1127
+ if (m_pool.m_opts.require_standard && !ignore_rejects.count("dust")) {
1128
  if (!PreCheckEphemeralTx(*ptx, m_pool.m_opts.dust_relay_feerate, ws.m_base_fees, ws.m_modified_fees, state)) {
1129
  return false; // state filled in by PreCheckEphemeralTx
1130
  }
1131
  }
1132
 
1133
+ // To avoid rejecting low-sigop bare-multisig transactions, the sigops
1134
+ // are counted a second time more accurately.
1135
+ if ((nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST) || (nBytesPerSigOpStrict && GetAccurateTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS) > ws.m_vsize * WITNESS_SCALE_FACTOR / nBytesPerSigOpStrict)) {
1136
+ MaybeRejectDbg(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
1137
  strprintf("%d", nSigOpsCost));
1138
+ }
1139
 
1140
  // No individual transactions are allowed below the min relay feerate except from disconnected blocks.
1141
  // This requirement, unlike CheckFeeRate, cannot be bypassed using m_package_feerates because,
 
1143
  // method of ensuring the tx remains bumped. For example, the fee-bumping child could disappear
1144
  // due to a replacement.
1145
  // The only exception is TRUC transactions.
1146
+ if ((ws.m_ptx->version != TRUC_VERSION || m_pool.m_opts.truc_policy != TRUCPolicy::Enforce) && ws.m_modified_fees < m_pool.m_opts.min_relay_feerate.GetFee(ws.m_vsize) && !args.m_ignore_rejects.count(rejectmsg_lowfee_relay)) {
1147
  // Even though this is a fee-related failure, this result is TX_MEMPOOL_POLICY, not
1148
  // TX_RECONSIDERABLE, because it cannot be bypassed using package validation.
1149
  return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "min relay fee not met",
 
1152
  // No individual transactions are allowed below the mempool min feerate except from disconnected
1153
  // blocks and transactions in a package. Package transactions will be checked using package
1154
  // feerate later.
1155
+ if (!args.m_package_feerates && !CheckFeeRate(ws.m_vsize, ws.m_modified_fees, state, args.m_ignore_rejects)) return false;
1156
 
1157
+ std::set<Txid> conflicts_as_a_set;
1158
+ std::transform(ws.m_conflicts_incl_policy.begin(), ws.m_conflicts_incl_policy.end(),
1159
+ std::inserter(conflicts_as_a_set, conflicts_as_a_set.end()),
1160
+ [](const std::pair<Txid, bool>& pair){ return pair.first; });
1161
+ ws.m_iters_conflicting = m_pool.GetIterSet(conflicts_as_a_set);
1162
 
1163
  // Note that these modifications are only applicable to single transaction scenarios;
1164
  // carve-outs are disabled for multi-transaction evaluations.
1165
  CTxMemPool::Limits maybe_rbf_limits = m_pool.m_opts.limits;
1166
 
1167
  // Calculate in-mempool ancestors, up to a limit.
1168
+ if (ws.m_conflicts_incl_policy.size() == 1 && args.m_allow_carveouts) {
1169
  // In general, when we receive an RBF transaction with mempool conflicts, we want to know whether we
1170
  // would meet the chain limits after the conflicts have been removed. However, there isn't a practical
1171
  // way to do this short of calculating the ancestor and descendant sets with an overlay cache of
 
1200
  maybe_rbf_limits.descendant_size_vbytes += conflict->GetSizeWithDescendants();
1201
  }
1202
 
1203
+ CTxMemPool::Limits limits;
1204
+ if (ignore_rejects.count("too-long-mempool-chain")) {
1205
+ limits = CTxMemPool::Limits::NoLimits();
1206
+ } else {
1207
+ limits = maybe_rbf_limits;
1208
+ }
1209
+ if (auto ancestors{m_subpackage.m_changeset->CalculateMemPoolAncestors(ws.m_tx_handle, limits)}) {
1210
  ws.m_ancestors = std::move(*ancestors);
1211
  } else {
1212
  // If CalculateMemPoolAncestors fails second time, we want the original error string.
 
1235
  .descendant_count = maybe_rbf_limits.descendant_count + 1,
1236
  .descendant_size_vbytes = maybe_rbf_limits.descendant_size_vbytes + EXTRA_DESCENDANT_TX_SIZE_LIMIT,
1237
  };
1238
+ if (ws.m_vsize > EXTRA_DESCENDANT_TX_SIZE_LIMIT || (ws.m_ptx->version == TRUC_VERSION && m_pool.m_opts.truc_policy == TRUCPolicy::Enforce)) {
1239
  return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "too-long-mempool-chain", error_message);
1240
  }
1241
  if (auto ancestors_retry{m_subpackage.m_changeset->CalculateMemPoolAncestors(ws.m_tx_handle, cpfp_carve_out_limits)}) {
 
1248
  // Even though just checking direct mempool parents for inheritance would be sufficient, we
1249
  // check using the full ancestor set here because it's more convenient to use what we have
1250
  // already calculated.
1251
+ if (m_pool.m_opts.truc_policy == TRUCPolicy::Enforce && !ignore_rejects.count("truc")) {
1252
+ if (const auto err{SingleTRUCChecks(ws.m_ptx, "truc-", reason, ignore_rejects, ws.m_ancestors, conflicts_as_a_set, ws.m_vsize)}) {
1253
  // Single transaction contexts only.
1254
  if (args.m_allow_sibling_eviction && err->second != nullptr) {
1255
  // We should only be considering where replacement is considered valid as well.
 
1257
 
1258
  // Potential sibling eviction. Add the sibling to our list of mempool conflicts to be
1259
  // included in RBF checks.
1260
+ ws.m_conflicts_incl_policy.emplace(err->second->GetHash(), false);
1261
+ conflicts_as_a_set.insert(err->second->GetHash());
1262
  // Adding the sibling to m_iters_conflicting here means that it doesn't count towards
1263
  // RBF Carve Out above. This is correct, since removing to-be-replaced transactions from
1264
  // the descendant count is done separately in SingleTRUCChecks for TRUC transactions.
 
1269
  // (which is normally done in PreChecks). However, the only way a TRUC transaction can
1270
  // have a non-TRUC and non-BIP125 descendant is due to a reorg.
1271
  } else {
1272
+ return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, reason, err->first);
1273
  }
1274
  }
1275
  }
 
1278
  // that we have the set of all ancestors we can detect this
1279
  // pathological case by making sure ws.m_conflicts and ws.m_ancestors don't
1280
  // intersect.
1281
+ bool has_policy_conflict{false};
1282
+ if (const auto err_string{EntriesAndTxidsDisjoint(ws.m_ancestors, ws.m_conflicts_incl_policy, hash, &has_policy_conflict)}) {
1283
  // We classify this as a consensus error because a transaction depending on something it
1284
  // conflicts with would be inconsistent.
1285
  return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-spends-conflicting-tx", *err_string);
1286
  }
1287
+ if (has_policy_conflict) {
1288
+ MaybeReject(TxValidationResult::TX_MEMPOOL_POLICY, "txn-spk-reused-chained");
1289
+ }
1290
 
1291
  // We want to detect conflicts in any tx in a package to trigger package RBF logic
1292
+ m_subpackage.m_rbf |= !ws.m_conflicts_incl_policy.empty();
1293
  return true;
1294
  }
1295
 
1296
+ bool MemPoolAccept::ReplacementChecks(ATMPArgs& args, Workspace& ws)
1297
  {
1298
  AssertLockHeld(cs_main);
1299
  AssertLockHeld(m_pool.cs);
 
1312
  // guarantee that this is incentive-compatible for miners, because it is possible for a
1313
  // descendant transaction of a direct conflict to pay a higher feerate than the transaction that
1314
  // might replace them, under these rules.
1315
+ if (!args.m_ignore_rejects.count("insufficient fee")) {
1316
  if (const auto err_string{PaysMoreThanConflicts(ws.m_iters_conflicting, newFeeRate, hash)}) {
1317
  // This fee-related failure is TX_RECONSIDERABLE because validating in a package may change
1318
  // the result.
1319
  return state.Invalid(TxValidationResult::TX_RECONSIDERABLE,
1320
  strprintf("insufficient fee%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
1321
  }
1322
+ } // ignore_rejects
1323
 
1324
  CTxMemPool::setEntries all_conflicts;
1325
 
1326
  // Calculate all conflicting entries and enforce Rule #5.
1327
+ if (const auto err_string{GetEntriesForConflicts(tx, m_pool, ws.m_iters_conflicting, all_conflicts, args.m_ignore_rejects)}) {
1328
  return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
1329
  strprintf("too many potential replacements%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
1330
  }
1331
  // Enforce Rule #2.
1332
+ if (!args.m_ignore_rejects.count("replacement-adds-unconfirmed")) {
1333
  if (const auto err_string{HasNoNewUnconfirmed(tx, m_pool, all_conflicts)}) {
1334
  // Sibling eviction is only done for TRUC transactions, which cannot have multiple ancestors.
1335
  Assume(!ws.m_sibling_eviction);
1336
  return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY,
1337
  strprintf("replacement-adds-unconfirmed%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
1338
  }
1339
+ } // ignore_rejects
1340
 
1341
  // Check if it's economically rational to mine this transaction rather than the ones it
1342
  // replaces and pays for its own relay fees. Enforce Rules #3 and #4.
 
1344
  m_subpackage.m_conflicting_fees += it->GetModifiedFee();
1345
  m_subpackage.m_conflicting_size += it->GetTxSize();
1346
  }
1347
+ if (!args.m_ignore_rejects.count("insufficient fee")) {
1348
  if (const auto err_string{PaysForRBF(m_subpackage.m_conflicting_fees, ws.m_modified_fees, ws.m_vsize,
1349
  m_pool.m_opts.incremental_relay_feerate, hash)}) {
1350
  // Result may change in a package context
1351
  return state.Invalid(TxValidationResult::TX_RECONSIDERABLE,
1352
  strprintf("insufficient fee%s", ws.m_sibling_eviction ? " (including sibling eviction)" : ""), *err_string);
1353
  }
1354
+ } // ignore_rejects
1355
 
1356
  // Add all the to-be-removed transactions to the changeset.
1357
  for (auto it : all_conflicts) {
 
1360
  return true;
1361
  }
1362
 
1363
+ bool MemPoolAccept::PackageMempoolChecks(const ATMPArgs& args, const std::vector<CTransactionRef>& txns,
1364
  std::vector<Workspace>& workspaces,
1365
  const int64_t total_vsize,
1366
  PackageValidationState& package_state)
 
1373
 
1374
  assert(txns.size() == workspaces.size());
1375
 
1376
+ util::Result<void> result = [&]() EXCLUSIVE_LOCKS_REQUIRED(m_pool.cs) {
1377
+ if (args.m_ignore_rejects.count("package-mempool-limits")) {
1378
+ return util::Result<void>();
1379
+ } else {
1380
+ return m_pool.CheckPackageLimits(txns, total_vsize);
1381
+ }
1382
+ }();
1383
  if (!result) {
1384
  // This is a package-wide error, separate from an individual transaction error.
1385
  return package_state.Invalid(PackageValidationResult::PCKG_POLICY, "package-mempool-limits", util::ErrorString(result).original);
 
1465
  return true;
1466
  }
1467
 
1468
+ unsigned int PolicyScriptVerifyFlags(const ignore_rejects_type& ignore_rejects)
1469
+ {
1470
+ if (ignore_rejects.empty()) {
1471
+ return STANDARD_SCRIPT_VERIFY_FLAGS;
1472
+ }
1473
+ if (ignore_rejects.count("non-mandatory-script-verify-flag")) {
1474
+ return MANDATORY_SCRIPT_VERIFY_FLAGS;
1475
+ }
1476
+
1477
+ unsigned int flags = STANDARD_SCRIPT_VERIFY_FLAGS;
1478
+ if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable")) {
1479
+ constexpr unsigned int upgradable_policy_flags =
1480
+ SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS |
1481
+ SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM |
1482
+ SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION |
1483
+ SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS |
1484
+ SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE;
1485
+ flags &= ~upgradable_policy_flags;
1486
+ } else {
1487
+ if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable-nops")) {
1488
+ flags &= ~SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS;
1489
+ }
1490
+ if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable-witness_program")) {
1491
+ flags &= ~SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM;
1492
+ }
1493
+ if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable-taproot_version")) {
1494
+ flags &= ~SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION;
1495
+ }
1496
+ if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable-op_success")) {
1497
+ flags &= ~SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS;
1498
+ }
1499
+ if (ignore_rejects.count("non-mandatory-script-verify-flag-upgradable-pubkeytype")) {
1500
+ flags &= ~SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE;
1501
+ }
1502
+ }
1503
+ if (ignore_rejects.count("non-mandatory-script-verify-flag-bip62")) {
1504
+ constexpr unsigned int bip62_policy_flags =
1505
+ SCRIPT_VERIFY_LOW_S |
1506
+ SCRIPT_VERIFY_SIGPUSHONLY | // NOTE: not actually set ever
1507
+ SCRIPT_VERIFY_MINIMALDATA;
1508
+ flags &= ~bip62_policy_flags;
1509
+ } else {
1510
+ if (ignore_rejects.count("non-mandatory-script-verify-flag-low_s")) {
1511
+ flags &= ~SCRIPT_VERIFY_LOW_S;
1512
+ }
1513
+ if (ignore_rejects.count("non-mandatory-script-verify-flag-minimaldata")) {
1514
+ flags &= ~SCRIPT_VERIFY_MINIMALDATA;
1515
+ }
1516
+ if (ignore_rejects.count("non-mandatory-script-verify-flag-cleanstack")) {
1517
+ flags &= ~SCRIPT_VERIFY_CLEANSTACK;
1518
+ }
1519
+ }
1520
+ if (ignore_rejects.count("non-mandatory-script-verify-flag-strictenc")) {
1521
+ flags &= ~SCRIPT_VERIFY_STRICTENC;
1522
+ }
1523
+ if (ignore_rejects.count("non-mandatory-script-verify-flag-minimalif")) {
1524
+ flags &= ~SCRIPT_VERIFY_MINIMALIF;
1525
+ }
1526
+ if (ignore_rejects.count("non-mandatory-script-verify-flag-nullfail")) {
1527
+ flags &= ~SCRIPT_VERIFY_NULLFAIL;
1528
+ }
1529
+ if (ignore_rejects.count("non-mandatory-script-verify-flag-witness_pubkeytype")) {
1530
+ flags &= ~SCRIPT_VERIFY_WITNESS_PUBKEYTYPE;
1531
+ }
1532
+ if (ignore_rejects.count("non-mandatory-script-verify-flag-const_scriptcode")) {
1533
+ flags &= ~SCRIPT_VERIFY_CONST_SCRIPTCODE;
1534
+ }
1535
+ flags |= MANDATORY_SCRIPT_VERIFY_FLAGS; // for safety
1536
+ return flags;
1537
+ }
1538
+
1539
  bool MemPoolAccept::PolicyScriptChecks(const ATMPArgs& args, Workspace& ws)
1540
  {
1541
  AssertLockHeld(cs_main);
 
1543
  const CTransaction& tx = *ws.m_ptx;
1544
  TxValidationState& state = ws.m_state;
1545
 
1546
+ const unsigned int scriptVerifyFlags = PolicyScriptVerifyFlags(args.m_ignore_rejects);
1547
 
1548
  // Check input scripts and signatures.
1549
  // This is done last to help prevent CPU exhaustion denial-of-service attacks.
 
1585
  unsigned int currentBlockScriptVerifyFlags{GetBlockScriptFlags(*m_active_chainstate.m_chain.Tip(), m_active_chainstate.m_chainman)};
1586
  if (!CheckInputsFromMempoolAndCache(tx, state, m_view, m_pool, currentBlockScriptVerifyFlags,
1587
  ws.m_precomputed_txdata, m_active_chainstate.CoinsTip(), GetValidationCache())) {
1588
+ LogError("BUG! PLEASE REPORT THIS! CheckInputScripts failed against latest-block but not STANDARD flags %s, %s", hash.ToString(), state.ToString());
1589
  return Assume(false);
1590
  }
1591
 
 
1710
  const CTransaction& tx = *ws.m_ptx;
1711
  const auto tx_info = NewMempoolTransactionInfo(ws.m_ptx, ws.m_base_fees,
1712
  ws.m_vsize, (*iter)->GetHeight(),
1713
+ args.m_ignore_rejects, args.m_package_submission,
1714
  IsCurrentForFeeEstimation(m_active_chainstate),
1715
  m_pool.HasNoInputsOf(tx));
1716
  m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());
 
1750
  }
1751
  }
1752
 
1753
+ if (m_subpackage.m_rbf && !ReplacementChecks(args, ws)) {
1754
  if (ws.m_state.GetResult() == TxValidationResult::TX_RECONSIDERABLE) {
1755
  // Failed for incentives-based fee reasons. Provide the effective feerate and which tx was included.
1756
  return MempoolAcceptResult::FeeFailure(ws.m_state, CFeeRate(ws.m_modified_fees, ws.m_vsize), single_wtxid);
 
1774
  FinalizeSubpackage(args);
1775
 
1776
  // Limit the mempool, if appropriate.
1777
+ if (!args.m_package_submission && !args.m_ignore_rejects.count(rejectmsg_mempoolfull)) {
1778
  LimitMempoolSize(m_pool, m_active_chainstate.CoinsTip());
1779
  // If mempool contents change, then the m_view cache is dirty. Given this isn't a package
1780
  // submission, we won't be using the cache anymore, but clear it anyway for clarity.
 
1793
  Assume(iter.has_value());
1794
  const auto tx_info = NewMempoolTransactionInfo(ws.m_ptx, ws.m_base_fees,
1795
  ws.m_vsize, (*iter)->GetHeight(),
1796
+ args.m_ignore_rejects, args.m_package_submission,
1797
  IsCurrentForFeeEstimation(m_active_chainstate),
1798
  m_pool.HasNoInputsOf(tx));
1799
  m_pool.m_opts.signals->TransactionAddedToMempool(tx_info, m_pool.GetAndIncrementSequence());
 
1860
 
1861
  // At this point we have all in-mempool ancestors, and we know every transaction's vsize.
1862
  // Run the TRUC checks on the package.
1863
+ if (m_pool.m_opts.truc_policy == TRUCPolicy::Enforce) {
1864
+ std::string reason;
1865
  for (Workspace& ws : workspaces) {
1866
+ if (auto err{PackageTRUCChecks(ws.m_ptx, ws.m_vsize, "truc-", reason, args.m_ignore_rejects, txns, ws.m_ancestors)}) {
1867
+ package_state.Invalid(PackageValidationResult::PCKG_POLICY, reason, err.value());
1868
  return PackageMempoolAcceptResult(package_state, {});
1869
  }
1870
+ }}
1871
 
1872
  // Transactions must meet two minimum feerates: the mempool minimum fee and min relay fee.
1873
  // For transactions consisting of exactly one child and its parents, it suffices to use the
 
1889
  [](const auto& ws) { return ws.m_ptx->GetWitnessHash(); });
1890
  TxValidationState placeholder_state;
1891
  if (args.m_package_feerates &&
1892
+ (!args.m_ignore_rejects.count("package-fee-too-low")) &&
1893
+ !CheckFeeRate(m_subpackage.m_total_vsize, m_subpackage.m_total_modified_fees, placeholder_state, empty_ignore_rejects)) {
1894
  package_state.Invalid(PackageValidationResult::PCKG_TX, "transaction failed");
1895
  return PackageMempoolAcceptResult(package_state, {{workspaces.back().m_ptx->GetWitnessHash(),
1896
  MempoolAcceptResult::FeeFailure(placeholder_state, CFeeRate(m_subpackage.m_total_modified_fees, m_subpackage.m_total_vsize), all_package_wtxids)}});
 
1898
 
1899
  // Apply package mempool ancestor/descendant limits. Skip if there is only one transaction,
1900
  // because it's unnecessary.
1901
+ if (txns.size() > 1 && !PackageMempoolChecks(args, txns, workspaces, m_subpackage.m_total_vsize, package_state)) {
1902
  return PackageMempoolAcceptResult(package_state, std::move(results));
1903
  }
1904
 
1905
  // Now that we've bounded the resulting possible ancestry count, check package for dust spends
1906
+ if (m_pool.m_opts.require_standard && !(args.m_ignore_rejects.count("dust") || args.m_ignore_rejects.count("unspent-dust") || args.m_ignore_rejects.count("missing-ephemeral-spends"))) {
1907
  TxValidationState child_state;
1908
  Wtxid child_wtxid;
1909
  if (!CheckEphemeralSpends(txns, m_pool.m_opts.dust_relay_feerate, m_pool, child_state, child_wtxid)) {
 
2153
  } // anon namespace
2154
 
2155
  MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTransactionRef& tx,
2156
+ int64_t accept_time, const ignore_rejects_type& ignore_rejects, bool test_accept)
2157
  {
2158
  AssertLockHeld(::cs_main);
2159
  const CChainParams& chainparams{active_chainstate.m_chainman.GetParams()};
 
2161
  CTxMemPool& pool{*active_chainstate.GetMempool()};
2162
 
2163
  std::vector<COutPoint> coins_to_uncache;
2164
+ auto args = MemPoolAccept::ATMPArgs::SingleAccept(chainparams, accept_time, ignore_rejects, coins_to_uncache, test_accept);
2165
  MempoolAcceptResult result = MemPoolAccept(pool, active_chainstate).AcceptSingleTransaction(tx, args);
2166
  if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) {
2167
  // Remove coins that were not present in the coins cache before calling
 
2183
  }
2184
 
2185
  PackageMempoolAcceptResult ProcessNewPackage(Chainstate& active_chainstate, CTxMemPool& pool,
2186
+ const Package& package, bool test_accept, const std::optional<CFeeRate>& client_maxfeerate, const ignore_rejects_type& ignore_rejects)
2187
  {
2188
  AssertLockHeld(cs_main);
2189
  assert(!package.empty());
 
2194
  auto result = [&]() EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
2195
  AssertLockHeld(cs_main);
2196
  if (test_accept) {
2197
+ auto args = MemPoolAccept::ATMPArgs::PackageTestAccept(chainparams, GetTime(), ignore_rejects, coins_to_uncache);
2198
  return MemPoolAccept(pool, active_chainstate).AcceptMultipleTransactions(package, args);
2199
  } else {
2200
+ auto args = MemPoolAccept::ATMPArgs::PackageChildWithParents(chainparams, GetTime(), coins_to_uncache, client_maxfeerate, ignore_rejects);
2201
  return MemPoolAccept(pool, active_chainstate).AcceptPackage(package, args);