@@ -541,6 +541,14 @@ class MemPoolAccept
541
541
// only tests that are fast should be done here (to avoid CPU DoS).
542
542
bool PreChecks (ATMPArgs& args, Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
543
543
544
+ // Run checks for mempool replace-by-fee.
545
+ bool ReplacementChecks (Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
546
+
547
+ // Enforce package mempool ancestor/descendant limits (distinct from individual
548
+ // ancestor/descendant limits done in PreChecks).
549
+ bool PackageMempoolChecks (const std::vector<CTransactionRef>& txns,
550
+ PackageValidationState& package_state) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
551
+
544
552
// Run the script checks using our policy flags. As this can be slow, we should
545
553
// only invoke this on transactions that have otherwise passed policy checks.
546
554
bool PolicyScriptChecks (const ATMPArgs& args, Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
@@ -823,43 +831,67 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
823
831
}
824
832
825
833
m_rbf = !ws.m_conflicts .empty ();
826
- if (m_rbf) {
827
- CFeeRate newFeeRate (ws.m_modified_fees , ws.m_vsize );
828
- // It's possible that the replacement pays more fees than its direct conflicts but not more
829
- // than all conflicts (i.e. the direct conflicts have high-fee descendants). However, if the
830
- // replacement doesn't pay more fees than its direct conflicts, then we can be sure it's not
831
- // more economically rational to mine. Before we go digging through the mempool for all
832
- // transactions that would need to be removed (direct conflicts and all descendants), check
833
- // that the replacement transaction pays more than its direct conflicts.
834
- if (const auto err_string{PaysMoreThanConflicts (ws.m_iters_conflicting , newFeeRate, hash)}) {
835
- return state.Invalid (TxValidationResult::TX_MEMPOOL_POLICY, " insufficient fee" , *err_string);
836
- }
834
+ return true ;
835
+ }
837
836
838
- // Calculate all conflicting entries and enforce BIP125 Rule #5.
839
- if (const auto err_string{GetEntriesForConflicts (tx, m_pool, ws.m_iters_conflicting , ws.m_all_conflicting )}) {
840
- return state.Invalid (TxValidationResult::TX_MEMPOOL_POLICY,
841
- " too many potential replacements" , *err_string);
842
- }
843
- // Enforce BIP125 Rule #2.
844
- if (const auto err_string{HasNoNewUnconfirmed (tx, m_pool, ws.m_iters_conflicting )}) {
845
- return state.Invalid (TxValidationResult::TX_MEMPOOL_POLICY,
846
- " replacement-adds-unconfirmed" , *err_string);
847
- }
837
+ bool MemPoolAccept::ReplacementChecks (Workspace& ws)
838
+ {
839
+ AssertLockHeld (cs_main);
840
+ AssertLockHeld (m_pool.cs );
848
841
849
- // Check if it's economically rational to mine this transaction rather than the ones it
850
- // replaces and pays for its own relay fees. Enforce BIP125 Rules #3 and #4.
851
- for (CTxMemPool::txiter it : ws.m_all_conflicting ) {
852
- ws.m_conflicting_fees += it->GetModifiedFee ();
853
- ws.m_conflicting_size += it->GetTxSize ();
854
- }
855
- if (const auto err_string{PaysForRBF (ws.m_conflicting_fees , ws.m_modified_fees , ws.m_vsize ,
856
- ::incrementalRelayFee, hash)}) {
857
- return state.Invalid (TxValidationResult::TX_MEMPOOL_POLICY, " insufficient fee" , *err_string);
858
- }
842
+ const CTransaction& tx = *ws.m_ptx ;
843
+ const uint256& hash = ws.m_hash ;
844
+ TxValidationState& state = ws.m_state ;
845
+
846
+ CFeeRate newFeeRate (ws.m_modified_fees , ws.m_vsize );
847
+ // It's possible that the replacement pays more fees than its direct conflicts but not more
848
+ // than all conflicts (i.e. the direct conflicts have high-fee descendants). However, if the
849
+ // replacement doesn't pay more fees than its direct conflicts, then we can be sure it's not
850
+ // more economically rational to mine. Before we go digging through the mempool for all
851
+ // transactions that would need to be removed (direct conflicts and all descendants), check
852
+ // that the replacement transaction pays more than its direct conflicts.
853
+ if (const auto err_string{PaysMoreThanConflicts (ws.m_iters_conflicting , newFeeRate, hash)}) {
854
+ return state.Invalid (TxValidationResult::TX_MEMPOOL_POLICY, " insufficient fee" , *err_string);
855
+ }
856
+
857
+ // Calculate all conflicting entries and enforce BIP125 Rule #5.
858
+ if (const auto err_string{GetEntriesForConflicts (tx, m_pool, ws.m_iters_conflicting , ws.m_all_conflicting )}) {
859
+ return state.Invalid (TxValidationResult::TX_MEMPOOL_POLICY,
860
+ " too many potential replacements" , *err_string);
861
+ }
862
+ // Enforce BIP125 Rule #2.
863
+ if (const auto err_string{HasNoNewUnconfirmed (tx, m_pool, ws.m_iters_conflicting )}) {
864
+ return state.Invalid (TxValidationResult::TX_MEMPOOL_POLICY,
865
+ " replacement-adds-unconfirmed" , *err_string);
866
+ }
867
+ // Check if it's economically rational to mine this transaction rather than the ones it
868
+ // replaces and pays for its own relay fees. Enforce BIP125 Rules #3 and #4.
869
+ for (CTxMemPool::txiter it : ws.m_all_conflicting ) {
870
+ ws.m_conflicting_fees += it->GetModifiedFee ();
871
+ ws.m_conflicting_size += it->GetTxSize ();
872
+ }
873
+ if (const auto err_string{PaysForRBF (ws.m_conflicting_fees , ws.m_modified_fees , ws.m_vsize ,
874
+ ::incrementalRelayFee, hash)}) {
875
+ return state.Invalid (TxValidationResult::TX_MEMPOOL_POLICY, " insufficient fee" , *err_string);
859
876
}
860
877
return true ;
861
878
}
862
879
880
+ bool MemPoolAccept::PackageMempoolChecks (const std::vector<CTransactionRef>& txns,
881
+ PackageValidationState& package_state)
882
+ {
883
+ AssertLockHeld (cs_main);
884
+ AssertLockHeld (m_pool.cs );
885
+
886
+ std::string err_string;
887
+ if (!m_pool.CheckPackageLimits (txns, m_limit_ancestors, m_limit_ancestor_size, m_limit_descendants,
888
+ m_limit_descendant_size, err_string)) {
889
+ // This is a package-wide error, separate from an individual transaction error.
890
+ return package_state.Invalid (PackageValidationResult::PCKG_POLICY, " package-mempool-limits" , err_string);
891
+ }
892
+ return true ;
893
+ }
894
+
863
895
bool MemPoolAccept::PolicyScriptChecks (const ATMPArgs& args, Workspace& ws)
864
896
{
865
897
const CTransaction& tx = *ws.m_ptx ;
@@ -966,6 +998,8 @@ MempoolAcceptResult MemPoolAccept::AcceptSingleTransaction(const CTransactionRef
966
998
967
999
if (!PreChecks (args, ws)) return MempoolAcceptResult::Failure (ws.m_state );
968
1000
1001
+ if (m_rbf && !ReplacementChecks (ws)) return MempoolAcceptResult::Failure (ws.m_state );
1002
+
969
1003
// Perform the inexpensive checks first and avoid hashing and signature verification unless
970
1004
// those checks pass, to mitigate CPU exhaustion denial-of-service attacks.
971
1005
if (!PolicyScriptChecks (args, ws)) return MempoolAcceptResult::Failure (ws.m_state );
@@ -1020,12 +1054,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
1020
1054
// because it's unnecessary. Also, CPFP carve out can increase the limit for individual
1021
1055
// transactions, but this exemption is not extended to packages in CheckPackageLimits().
1022
1056
std::string err_string;
1023
- if (txns.size () > 1 &&
1024
- !m_pool.CheckPackageLimits (txns, m_limit_ancestors, m_limit_ancestor_size, m_limit_descendants,
1025
- m_limit_descendant_size, err_string)) {
1026
- // All transactions must have individually passed mempool ancestor and descendant limits
1027
- // inside of PreChecks(), so this is separate from an individual transaction error.
1028
- package_state.Invalid (PackageValidationResult::PCKG_POLICY, " package-mempool-limits" , err_string);
1057
+ if (txns.size () > 1 && !PackageMempoolChecks (txns, package_state)) {
1029
1058
return PackageMempoolAcceptResult (package_state, std::move (results));
1030
1059
}
1031
1060
0 commit comments