@@ -455,7 +455,7 @@ class MemPoolAccept
455455 * any transaction spending the same inputs as a transaction in the mempool is considered
456456 * a conflict. */
457457 const bool m_allow_replacement;
458- /* * When true, the mempool will not be trimmed when individual transactions are submitted in
458+ /* * When true, the mempool will not be trimmed when any transactions are submitted in
459459 * Finalize(). Instead, limits should be enforced at the end to ensure the package is not
460460 * partially submitted.
461461 */
@@ -516,7 +516,7 @@ class MemPoolAccept
516516 /* m_coins_to_uncache */ package_args.m_coins_to_uncache ,
517517 /* m_test_accept */ package_args.m_test_accept ,
518518 /* m_allow_replacement */ true ,
519- /* m_package_submission */ false ,
519+ /* m_package_submission */ true , // do not LimitMempoolSize in Finalize()
520520 /* m_package_feerates */ false , // only 1 transaction
521521 };
522522 }
@@ -652,8 +652,7 @@ class MemPoolAccept
652652
653653 // Submit all transactions to the mempool and call ConsensusScriptChecks to add to the script
654654 // cache - should only be called after successful validation of all transactions in the package.
655- // The package may end up partially-submitted after size limiting; returns true if all
656- // transactions are successfully added to the mempool, false otherwise.
655+ // Does not call LimitMempoolSize(), so mempool max_size_bytes may be temporarily exceeded.
657656 bool SubmitPackage (const ATMPArgs& args, std::vector<Workspace>& workspaces, PackageValidationState& package_state,
658657 std::map<uint256, MempoolAcceptResult>& results)
659658 EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
@@ -1187,32 +1186,21 @@ bool MemPoolAccept::SubmitPackage(const ATMPArgs& args, std::vector<Workspace>&
11871186 }
11881187 }
11891188
1190- // It may or may not be the case that all the transactions made it into the mempool. Regardless,
1191- // make sure we haven't exceeded max mempool size.
1192- LimitMempoolSize (m_pool, m_active_chainstate.CoinsTip ());
1193-
11941189 std::vector<uint256> all_package_wtxids;
11951190 all_package_wtxids.reserve (workspaces.size ());
11961191 std::transform (workspaces.cbegin (), workspaces.cend (), std::back_inserter (all_package_wtxids),
11971192 [](const auto & ws) { return ws.m_ptx ->GetWitnessHash (); });
1198- // Find the wtxids of the transactions that made it into the mempool. Allow partial submission,
1199- // but don't report success unless they all made it into the mempool .
1193+
1194+ // Add successful results. The returned results may change later if LimitMempoolSize() evicts them .
12001195 for (Workspace& ws : workspaces) {
12011196 const auto effective_feerate = args.m_package_feerates ? ws.m_package_feerate :
12021197 CFeeRate{ws.m_modified_fees , static_cast <uint32_t >(ws.m_vsize )};
12031198 const auto effective_feerate_wtxids = args.m_package_feerates ? all_package_wtxids :
12041199 std::vector<uint256>({ws.m_ptx ->GetWitnessHash ()});
1205- if (m_pool.exists (GenTxid::Wtxid (ws.m_ptx ->GetWitnessHash ()))) {
1206- results.emplace (ws.m_ptx ->GetWitnessHash (),
1207- MempoolAcceptResult::Success (std::move (ws.m_replaced_transactions ), ws.m_vsize ,
1208- ws.m_base_fees , effective_feerate, effective_feerate_wtxids));
1209- GetMainSignals ().TransactionAddedToMempool (ws.m_ptx , m_pool.GetAndIncrementSequence ());
1210- } else {
1211- all_submitted = false ;
1212- ws.m_state .Invalid (TxValidationResult::TX_MEMPOOL_POLICY, " mempool full" );
1213- package_state.Invalid (PackageValidationResult::PCKG_TX, " transaction failed" );
1214- results.emplace (ws.m_ptx ->GetWitnessHash (), MempoolAcceptResult::Failure (ws.m_state ));
1215- }
1200+ results.emplace (ws.m_ptx ->GetWitnessHash (),
1201+ MempoolAcceptResult::Success (std::move (ws.m_replaced_transactions ), ws.m_vsize ,
1202+ ws.m_base_fees , effective_feerate, effective_feerate_wtxids));
1203+ GetMainSignals ().TransactionAddedToMempool (ws.m_ptx , m_pool.GetAndIncrementSequence ());
12161204 }
12171205 return all_submitted;
12181206}
@@ -1518,12 +1506,26 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
15181506 AcceptSubPackage (txns_package_eval, args);
15191507 PackageValidationState& package_state_final = multi_submission_result.m_state ;
15201508
1509+ // Make sure we haven't exceeded max mempool size.
1510+ // Package transactions that were submitted to mempool or already in mempool may be evicted.
1511+ LimitMempoolSize (m_pool, m_active_chainstate.CoinsTip ());
1512+
15211513 for (const auto & tx : package) {
15221514 const auto & wtxid = tx->GetWitnessHash ();
15231515 if (multi_submission_result.m_tx_results .count (wtxid) > 0 ) {
15241516 // We shouldn't have re-submitted if the tx result was already in results_final.
15251517 Assume (results_final.count (wtxid) == 0 );
1526- results_final.emplace (wtxid, multi_submission_result.m_tx_results .at (wtxid));
1518+ // If it was submitted, check to see if the tx is still in the mempool. It could have
1519+ // been evicted due to LimitMempoolSize() above.
1520+ const auto & txresult = multi_submission_result.m_tx_results .at (wtxid);
1521+ if (txresult.m_result_type == MempoolAcceptResult::ResultType::VALID && !m_pool.exists (GenTxid::Wtxid (wtxid))) {
1522+ package_state_final.Invalid (PackageValidationResult::PCKG_TX, " transaction failed" );
1523+ TxValidationState mempool_full_state;
1524+ mempool_full_state.Invalid (TxValidationResult::TX_MEMPOOL_POLICY, " mempool full" );
1525+ results_final.emplace (wtxid, MempoolAcceptResult::Failure (mempool_full_state));
1526+ } else {
1527+ results_final.emplace (wtxid, txresult);
1528+ }
15271529 } else if (const auto it{results_final.find (wtxid)}; it != results_final.end ()) {
15281530 // Already-in-mempool transaction. Check to see if it's still there, as it could have
15291531 // been evicted when LimitMempoolSize() was called.
0 commit comments