@@ -663,18 +663,35 @@ class MemPoolAccept
663
663
PrecomputedTransactionData m_precomputed_txdata;
664
664
};
665
665
666
+ static inline bool MaybeReject_ (TxValidationResult reason, const std::string& reason_str, const std::string& debug_msg, const ignore_rejects_type& ignore_rejects, TxValidationState& state) {
667
+ if (ignore_rejects.count (reason_str)) {
668
+ return false ;
669
+ }
670
+
671
+ state.Invalid (reason, reason_str, debug_msg);
672
+ return true ;
673
+ }
674
+
675
+ #define MaybeRejectDbg (reason, reason_str, debug_msg ) do { \
676
+ if (MaybeReject_ (reason, reason_str, debug_msg, ignore_rejects, state)) { \
677
+ return false ; \
678
+ } \
679
+ } while (0 )
680
+
681
+ #define MaybeReject (reason, reason_str ) MaybeRejectDbg(reason, reason_str, " " )
682
+
666
683
// Run the policy checks on a given transaction, excluding any script checks.
667
684
// Looks up inputs, calculates feerate, considers replacement, evaluates
668
685
// package limits, etc. As this function can be invoked for "free" by a peer,
669
686
// only tests that are fast should be done here (to avoid CPU DoS).
670
687
bool PreChecks (ATMPArgs& args, Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
671
688
672
689
// Run checks for mempool replace-by-fee, only used in AcceptSingleTransaction.
673
- bool ReplacementChecks (Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
690
+ bool ReplacementChecks (ATMPArgs& args, Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
674
691
675
692
// Enforce package mempool ancestor/descendant limits (distinct from individual
676
693
// ancestor/descendant limits done in PreChecks) and run Package RBF checks.
677
- bool PackageMempoolChecks (const std::vector<CTransactionRef>& txns,
694
+ bool PackageMempoolChecks (const ATMPArgs& args, const std::vector<CTransactionRef>& txns,
678
695
std::vector<Workspace>& workspaces,
679
696
int64_t total_vsize,
680
697
PackageValidationState& package_state) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
@@ -776,6 +793,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
776
793
777
794
// Copy/alias what we need out of args
778
795
const int64_t nAcceptTime = args.m_accept_time ;
796
+ const ignore_rejects_type& ignore_rejects = args.m_ignore_rejects ;
779
797
std::vector<COutPoint>& coins_to_uncache = args.m_coins_to_uncache ;
780
798
781
799
// Alias what we need out of ws
@@ -798,13 +816,13 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
798
816
799
817
// Transactions smaller than 65 non-witness bytes are not relayed to mitigate CVE-2017-12842.
800
818
if (::GetSerializeSize (TX_NO_WITNESS (tx)) < MIN_STANDARD_TX_NONWITNESS_SIZE)
801
- return state. Invalid (TxValidationResult::TX_NOT_STANDARD, " tx-size-small" );
819
+ MaybeReject (TxValidationResult::TX_NOT_STANDARD, " tx-size-small" );
802
820
803
821
// Only accept nLockTime-using transactions that can be mined in the next
804
822
// block; we don't want our mempool filled up with transactions that can't
805
823
// be mined yet.
806
824
if (!CheckFinalTxAtTip (*Assert (m_active_chainstate.m_chain .Tip ()), tx)) {
807
- return state. Invalid (TxValidationResult::TX_PREMATURE_SPEND, " non-final" );
825
+ MaybeReject (TxValidationResult::TX_PREMATURE_SPEND, " non-final" );
808
826
}
809
827
810
828
if (m_pool.exists (GenTxid::Wtxid (tx.GetWitnessHash ()))) {
@@ -839,7 +857,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
839
857
//
840
858
// Replaceability signaling of the original transactions may be
841
859
// ignored due to node setting.
842
- const bool allow_rbf{m_pool.m_opts .full_rbf || SignalsOptInRBF (*ptxConflicting) || ptxConflicting->version == TRUC_VERSION};
860
+ const bool allow_rbf{( m_pool.m_opts .full_rbf || ignore_rejects. count ( " txn-mempool-conflict " )) || SignalsOptInRBF (*ptxConflicting) || ptxConflicting->version == TRUC_VERSION};
843
861
if (!allow_rbf) {
844
862
return state.Invalid (TxValidationResult::TX_MEMPOOL_POLICY, " txn-mempool-conflict" );
845
863
}
@@ -891,6 +909,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
891
909
// Pass in m_view which has all of the relevant inputs cached. Note that, since m_view's
892
910
// backend was removed, it no longer pulls coins from the mempool.
893
911
const std::optional<LockPoints> lock_points{CalculateLockPointsAtTip (m_active_chainstate.m_chain .Tip (), m_view, tx)};
912
+ // NOTE: The miner doesn't check this again, so for now it may not be overridden.
894
913
if (!lock_points.has_value () || !CheckSequenceLocksAtTip (m_active_chainstate.m_chain .Tip (), *lock_points)) {
895
914
return state.Invalid (TxValidationResult::TX_PREMATURE_SPEND, " non-BIP68-final" );
896
915
}
@@ -906,7 +925,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
906
925
907
926
// Check for non-standard witnesses.
908
927
if (tx.HasWitness () && m_pool.m_opts .require_standard && !IsWitnessStandard (tx, m_view)) {
909
- return state. Invalid (TxValidationResult::TX_WITNESS_MUTATED, " bad-witness-nonstandard" );
928
+ MaybeReject (TxValidationResult::TX_WITNESS_MUTATED, " bad-witness-nonstandard" );
910
929
}
911
930
912
931
int64_t nSigOpsCost = GetTransactionSigOpCost (tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS);
@@ -934,7 +953,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
934
953
ws.m_vsize = entry->GetTxSize ();
935
954
936
955
if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)
937
- return state. Invalid (TxValidationResult::TX_NOT_STANDARD, " bad-txns-too-many-sigops" ,
956
+ MaybeRejectDbg (TxValidationResult::TX_NOT_STANDARD, " bad-txns-too-many-sigops" ,
938
957
strprintf (" %d" , nSigOpsCost));
939
958
940
959
// No individual transactions are allowed below the min relay feerate except from disconnected blocks.
@@ -996,7 +1015,13 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
996
1015
maybe_rbf_limits.descendant_size_vbytes += conflict->GetSizeWithDescendants ();
997
1016
}
998
1017
999
- if (auto ancestors{m_pool.CalculateMemPoolAncestors (*entry, maybe_rbf_limits)}) {
1018
+ CTxMemPool::Limits limits;
1019
+ if (ignore_rejects.count (" too-long-mempool-chain" )) {
1020
+ limits = CTxMemPool::Limits::NoLimits ();
1021
+ } else {
1022
+ limits = maybe_rbf_limits;
1023
+ }
1024
+ if (auto ancestors{m_pool.CalculateMemPoolAncestors (*entry, limits)}) {
1000
1025
ws.m_ancestors = std::move (*ancestors);
1001
1026
} else {
1002
1027
// If CalculateMemPoolAncestors fails second time, we want the original error string.
@@ -1076,7 +1101,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
1076
1101
return true ;
1077
1102
}
1078
1103
1079
- bool MemPoolAccept::ReplacementChecks (Workspace& ws)
1104
+ bool MemPoolAccept::ReplacementChecks (ATMPArgs& args, Workspace& ws)
1080
1105
{
1081
1106
AssertLockHeld (cs_main);
1082
1107
AssertLockHeld (m_pool.cs );
@@ -1095,42 +1120,48 @@ bool MemPoolAccept::ReplacementChecks(Workspace& ws)
1095
1120
// guarantee that this is incentive-compatible for miners, because it is possible for a
1096
1121
// descendant transaction of a direct conflict to pay a higher feerate than the transaction that
1097
1122
// might replace them, under these rules.
1123
+ if (!args.m_ignore_rejects .count (" insufficient fee" )) {
1098
1124
if (const auto err_string{PaysMoreThanConflicts (ws.m_iters_conflicting , newFeeRate, hash)}) {
1099
1125
// This fee-related failure is TX_RECONSIDERABLE because validating in a package may change
1100
1126
// the result.
1101
1127
return state.Invalid (TxValidationResult::TX_RECONSIDERABLE,
1102
1128
strprintf (" insufficient fee%s" , ws.m_sibling_eviction ? " (including sibling eviction)" : " " ), *err_string);
1103
1129
}
1130
+ } // ignore_rejects
1104
1131
1105
1132
// Calculate all conflicting entries and enforce Rule #5.
1106
- if (const auto err_string{GetEntriesForConflicts (tx, m_pool, ws.m_iters_conflicting , m_subpackage.m_all_conflicts )}) {
1133
+ if (const auto err_string{GetEntriesForConflicts (tx, m_pool, ws.m_iters_conflicting , m_subpackage.m_all_conflicts , args. m_ignore_rejects )}) {
1107
1134
return state.Invalid (TxValidationResult::TX_MEMPOOL_POLICY,
1108
1135
strprintf (" too many potential replacements%s" , ws.m_sibling_eviction ? " (including sibling eviction)" : " " ), *err_string);
1109
1136
}
1110
1137
// Enforce Rule #2.
1138
+ if (!args.m_ignore_rejects .count (" replacement-adds-unconfirmed" )) {
1111
1139
if (const auto err_string{HasNoNewUnconfirmed (tx, m_pool, m_subpackage.m_all_conflicts )}) {
1112
1140
// Sibling eviction is only done for TRUC transactions, which cannot have multiple ancestors.
1113
1141
Assume (!ws.m_sibling_eviction );
1114
1142
return state.Invalid (TxValidationResult::TX_MEMPOOL_POLICY,
1115
1143
strprintf (" replacement-adds-unconfirmed%s" , ws.m_sibling_eviction ? " (including sibling eviction)" : " " ), *err_string);
1116
1144
}
1145
+ } // ignore_rejects
1117
1146
1118
1147
// Check if it's economically rational to mine this transaction rather than the ones it
1119
1148
// replaces and pays for its own relay fees. Enforce Rules #3 and #4.
1120
1149
for (CTxMemPool::txiter it : m_subpackage.m_all_conflicts ) {
1121
1150
m_subpackage.m_conflicting_fees += it->GetModifiedFee ();
1122
1151
m_subpackage.m_conflicting_size += it->GetTxSize ();
1123
1152
}
1153
+ if (!args.m_ignore_rejects .count (" insufficient fee" )) {
1124
1154
if (const auto err_string{PaysForRBF (m_subpackage.m_conflicting_fees , ws.m_modified_fees , ws.m_vsize ,
1125
1155
m_pool.m_opts .incremental_relay_feerate , hash)}) {
1126
1156
// Result may change in a package context
1127
1157
return state.Invalid (TxValidationResult::TX_RECONSIDERABLE,
1128
1158
strprintf (" insufficient fee%s" , ws.m_sibling_eviction ? " (including sibling eviction)" : " " ), *err_string);
1129
1159
}
1160
+ } // ignore_rejects
1130
1161
return true ;
1131
1162
}
1132
1163
1133
- bool MemPoolAccept::PackageMempoolChecks (const std::vector<CTransactionRef>& txns,
1164
+ bool MemPoolAccept::PackageMempoolChecks (const ATMPArgs& args, const std::vector<CTransactionRef>& txns,
1134
1165
std::vector<Workspace>& workspaces,
1135
1166
const int64_t total_vsize,
1136
1167
PackageValidationState& package_state)
@@ -1144,7 +1175,13 @@ bool MemPoolAccept::PackageMempoolChecks(const std::vector<CTransactionRef>& txn
1144
1175
1145
1176
assert (txns.size () == workspaces.size ());
1146
1177
1147
- auto result = m_pool.CheckPackageLimits (txns, total_vsize);
1178
+ util::Result<void > result = [&]() EXCLUSIVE_LOCKS_REQUIRED (m_pool.cs ) {
1179
+ if (args.m_ignore_rejects .count (" package-mempool-limits" )) {
1180
+ return util::Result<void >();
1181
+ } else {
1182
+ return m_pool.CheckPackageLimits (txns, total_vsize);
1183
+ }
1184
+ }();
1148
1185
if (!result) {
1149
1186
// This is a package-wide error, separate from an individual transaction error.
1150
1187
return package_state.Invalid (PackageValidationResult::PCKG_POLICY, " package-mempool-limits" , util::ErrorString (result).original );
@@ -1370,7 +1407,7 @@ bool MemPoolAccept::SubmitPackage(const ATMPArgs& args, std::vector<Workspace>&
1370
1407
// Re-calculate mempool ancestors to call addUnchecked(). They may have changed since the
1371
1408
// last calculation done in PreChecks, since package ancestors have already been submitted.
1372
1409
{
1373
- auto ancestors{m_pool.CalculateMemPoolAncestors (*ws.m_entry , m_pool. m_opts . limits )};
1410
+ auto ancestors{m_pool.CalculateMemPoolAncestors (*ws.m_entry , CTxMemPool::Limits::NoLimits () )};
1374
1411
if (!ancestors) {
1375
1412
results.emplace (ws.m_ptx ->GetWitnessHash (), MempoolAcceptResult::Failure (ws.m_state ));
1376
1413
// Since PreChecks() and PackageMempoolChecks() both enforce limits, this should never fail.
@@ -1452,7 +1489,7 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
1452
1489
return MempoolAcceptResult::Failure (ws.m_state );
1453
1490
}
1454
1491
1455
- if (m_subpackage.m_rbf && !ReplacementChecks (ws)) {
1492
+ if (m_subpackage.m_rbf && !ReplacementChecks (args, ws)) {
1456
1493
if (ws.m_state .GetResult () == TxValidationResult::TX_RECONSIDERABLE) {
1457
1494
// Failed for incentives-based fee reasons. Provide the effective feerate and which tx was included.
1458
1495
return MempoolAcceptResult::FeeFailure (ws.m_state , CFeeRate (ws.m_modified_fees , ws.m_vsize ), single_wtxid);
@@ -1586,7 +1623,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
1586
1623
1587
1624
// Apply package mempool ancestor/descendant limits. Skip if there is only one transaction,
1588
1625
// because it's unnecessary.
1589
- if (txns.size () > 1 && !PackageMempoolChecks (txns, workspaces, m_subpackage.m_total_vsize , package_state)) {
1626
+ if (txns.size () > 1 && !PackageMempoolChecks (args, txns, workspaces, m_subpackage.m_total_vsize , package_state)) {
1590
1627
return PackageMempoolAcceptResult (package_state, std::move (results));
1591
1628
}
1592
1629
0 commit comments