@@ -455,7 +455,7 @@ class MemPoolAccept
455
455
* any transaction spending the same inputs as a transaction in the mempool is considered
456
456
* a conflict. */
457
457
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
459
459
* Finalize(). Instead, limits should be enforced at the end to ensure the package is not
460
460
* partially submitted.
461
461
*/
@@ -516,7 +516,7 @@ class MemPoolAccept
516
516
/* m_coins_to_uncache */ package_args.m_coins_to_uncache ,
517
517
/* m_test_accept */ package_args.m_test_accept ,
518
518
/* m_allow_replacement */ true ,
519
- /* m_package_submission */ false ,
519
+ /* m_package_submission */ true , // do not LimitMempoolSize in Finalize()
520
520
/* m_package_feerates */ false , // only 1 transaction
521
521
};
522
522
}
@@ -652,8 +652,7 @@ class MemPoolAccept
652
652
653
653
// Submit all transactions to the mempool and call ConsensusScriptChecks to add to the script
654
654
// 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.
657
656
bool SubmitPackage (const ATMPArgs& args, std::vector<Workspace>& workspaces, PackageValidationState& package_state,
658
657
std::map<uint256, MempoolAcceptResult>& results)
659
658
EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
@@ -1187,32 +1186,21 @@ bool MemPoolAccept::SubmitPackage(const ATMPArgs& args, std::vector<Workspace>&
1187
1186
}
1188
1187
}
1189
1188
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
-
1194
1189
std::vector<uint256> all_package_wtxids;
1195
1190
all_package_wtxids.reserve (workspaces.size ());
1196
1191
std::transform (workspaces.cbegin (), workspaces.cend (), std::back_inserter (all_package_wtxids),
1197
1192
[](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 .
1200
1195
for (Workspace& ws : workspaces) {
1201
1196
const auto effective_feerate = args.m_package_feerates ? ws.m_package_feerate :
1202
1197
CFeeRate{ws.m_modified_fees , static_cast <uint32_t >(ws.m_vsize )};
1203
1198
const auto effective_feerate_wtxids = args.m_package_feerates ? all_package_wtxids :
1204
1199
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 ());
1216
1204
}
1217
1205
return all_submitted;
1218
1206
}
@@ -1518,12 +1506,26 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
1518
1506
AcceptSubPackage (txns_package_eval, args);
1519
1507
PackageValidationState& package_state_final = multi_submission_result.m_state ;
1520
1508
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
+
1521
1513
for (const auto & tx : package) {
1522
1514
const auto & wtxid = tx->GetWitnessHash ();
1523
1515
if (multi_submission_result.m_tx_results .count (wtxid) > 0 ) {
1524
1516
// We shouldn't have re-submitted if the tx result was already in results_final.
1525
1517
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
+ }
1527
1529
} else if (const auto it{results_final.find (wtxid)}; it != results_final.end ()) {
1528
1530
// Already-in-mempool transaction. Check to see if it's still there, as it could have
1529
1531
// been evicted when LimitMempoolSize() was called.
0 commit comments