@@ -478,6 +478,9 @@ class MemPoolAccept
478478 */
479479 const std::optional<CFeeRate> m_client_maxfeerate;
480480
481+ /* * Whether CPFP carveout and RBF carveout are granted. */
482+ const bool m_allow_carveouts;
483+
481484 /* * Parameters for single transaction mempool validation. */
482485 static ATMPArgs SingleAccept (const CChainParams& chainparams, int64_t accept_time,
483486 bool bypass_limits, std::vector<COutPoint>& coins_to_uncache,
@@ -492,6 +495,7 @@ class MemPoolAccept
492495 /* m_package_submission */ false ,
493496 /* m_package_feerates */ false ,
494497 /* m_client_maxfeerate */ {}, // checked by caller
498+ /* m_allow_carveouts */ true ,
495499 };
496500 }
497501
@@ -508,6 +512,7 @@ class MemPoolAccept
508512 /* m_package_submission */ false , // not submitting to mempool
509513 /* m_package_feerates */ false ,
510514 /* m_client_maxfeerate */ {}, // checked by caller
515+ /* m_allow_carveouts */ false ,
511516 };
512517 }
513518
@@ -524,6 +529,7 @@ class MemPoolAccept
524529 /* m_package_submission */ true ,
525530 /* m_package_feerates */ true ,
526531 /* m_client_maxfeerate */ client_maxfeerate,
532+ /* m_allow_carveouts */ false ,
527533 };
528534 }
529535
@@ -539,6 +545,7 @@ class MemPoolAccept
539545 /* m_package_submission */ true , // do not LimitMempoolSize in Finalize()
540546 /* m_package_feerates */ false , // only 1 transaction
541547 /* m_client_maxfeerate */ package_args.m_client_maxfeerate ,
548+ /* m_allow_carveouts */ false ,
542549 };
543550 }
544551
@@ -554,7 +561,8 @@ class MemPoolAccept
554561 bool allow_sibling_eviction,
555562 bool package_submission,
556563 bool package_feerates,
557- std::optional<CFeeRate> client_maxfeerate)
564+ std::optional<CFeeRate> client_maxfeerate,
565+ bool allow_carveouts)
558566 : m_chainparams{chainparams},
559567 m_accept_time{accept_time},
560568 m_bypass_limits{bypass_limits},
@@ -564,7 +572,8 @@ class MemPoolAccept
564572 m_allow_sibling_eviction{allow_sibling_eviction},
565573 m_package_submission{package_submission},
566574 m_package_feerates{package_feerates},
567- m_client_maxfeerate{client_maxfeerate}
575+ m_client_maxfeerate{client_maxfeerate},
576+ m_allow_carveouts{allow_carveouts}
568577 {
569578 }
570579 };
@@ -917,7 +926,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
917926 CTxMemPool::Limits maybe_rbf_limits = m_pool.m_opts .limits ;
918927
919928 // Calculate in-mempool ancestors, up to a limit.
920- if (ws.m_conflicts .size () == 1 ) {
929+ if (ws.m_conflicts .size () == 1 && args. m_allow_carveouts ) {
921930 // In general, when we receive an RBF transaction with mempool conflicts, we want to know whether we
922931 // would meet the chain limits after the conflicts have been removed. However, there isn't a practical
923932 // way to do this short of calculating the ancestor and descendant sets with an overlay cache of
@@ -956,6 +965,13 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
956965 ws.m_ancestors = std::move (*ancestors);
957966 } else {
958967 // If CalculateMemPoolAncestors fails second time, we want the original error string.
968+ const auto error_message{util::ErrorString (ancestors).original };
969+
970+ // Carve-out is not allowed in this context; fail
971+ if (!args.m_allow_carveouts ) {
972+ return state.Invalid (TxValidationResult::TX_MEMPOOL_POLICY, " too-long-mempool-chain" , error_message);
973+ }
974+
959975 // Contracting/payment channels CPFP carve-out:
960976 // If the new transaction is relatively small (up to 40k weight)
961977 // and has at most one ancestor (ie ancestor limit of 2, including
@@ -974,7 +990,6 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
974990 .descendant_count = maybe_rbf_limits.descendant_count + 1 ,
975991 .descendant_size_vbytes = maybe_rbf_limits.descendant_size_vbytes + EXTRA_DESCENDANT_TX_SIZE_LIMIT,
976992 };
977- const auto error_message{util::ErrorString (ancestors).original };
978993 if (ws.m_vsize > EXTRA_DESCENDANT_TX_SIZE_LIMIT || ws.m_ptx ->nVersion == 3 ) {
979994 return state.Invalid (TxValidationResult::TX_MEMPOOL_POLICY, " too-long-mempool-chain" , error_message);
980995 }
@@ -1431,9 +1446,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptMultipleTransactions(const std::
14311446 }
14321447
14331448 // Apply package mempool ancestor/descendant limits. Skip if there is only one transaction,
1434- // because it's unnecessary. Also, CPFP carve out can increase the limit for individual
1435- // transactions, but this exemption is not extended to packages in CheckPackageLimits().
1436- std::string err_string;
1449+ // because it's unnecessary.
14371450 if (txns.size () > 1 && !PackageMempoolChecks (txns, m_total_vsize, package_state)) {
14381451 return PackageMempoolAcceptResult (package_state, std::move (results));
14391452 }
0 commit comments