@@ -1672,10 +1672,14 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptSubPackage(const std::vector<CTr
1672
1672
1673
1673
PackageMempoolAcceptResult MemPoolAccept::AcceptPackage (const Package& package, ATMPArgs& args)
1674
1674
{
1675
+ Assert (!package.empty ());
1675
1676
AssertLockHeld (cs_main);
1676
1677
// Used if returning a PackageMempoolAcceptResult directly from this function.
1677
1678
PackageValidationState package_state_quit_early;
1678
1679
1680
+ // There are two topologies we are able to handle through this function:
1681
+ // (1) A single transaction
1682
+ // (2) A child-with-unconfirmed-parents package.
1679
1683
// Check that the package is well-formed. If it isn't, we won't try to validate any of the
1680
1684
// transactions and thus won't return any MempoolAcceptResults, just a package-wide error.
1681
1685
@@ -1684,48 +1688,50 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
1684
1688
return PackageMempoolAcceptResult (package_state_quit_early, {});
1685
1689
}
1686
1690
1687
- // All transactions in the package must be a parent of the last transaction. This is just an
1688
- // opportunity for us to fail fast on a context-free check without taking the mempool lock.
1689
- if (!IsChildWithParents (package)) {
1690
- package_state_quit_early.Invalid (PackageValidationResult::PCKG_POLICY, " package-not-child-with-parents" );
1691
- return PackageMempoolAcceptResult (package_state_quit_early, {});
1692
- }
1693
-
1694
- // IsChildWithParents() guarantees the package is > 1 transactions.
1695
- assert (package.size () > 1 );
1696
- // The package must be 1 child with all of its unconfirmed parents. The package is expected to
1697
- // be sorted, so the last transaction is the child.
1698
- const auto & child = package.back ();
1699
- std::unordered_set<uint256, SaltedTxidHasher> unconfirmed_parent_txids;
1700
- std::transform (package.cbegin (), package.cend () - 1 ,
1701
- std::inserter (unconfirmed_parent_txids, unconfirmed_parent_txids.end ()),
1702
- [](const auto & tx) { return tx->GetHash (); });
1703
-
1704
- // All child inputs must refer to a preceding package transaction or a confirmed UTXO. The only
1705
- // way to verify this is to look up the child's inputs in our current coins view (not including
1706
- // mempool), and enforce that all parents not present in the package be available at chain tip.
1707
- // Since this check can bring new coins into the coins cache, keep track of these coins and
1708
- // uncache them if we don't end up submitting this package to the mempool.
1709
- const CCoinsViewCache& coins_tip_cache = m_active_chainstate.CoinsTip ();
1710
- for (const auto & input : child->vin ) {
1711
- if (!coins_tip_cache.HaveCoinInCache (input.prevout )) {
1712
- args.m_coins_to_uncache .push_back (input.prevout );
1713
- }
1714
- }
1715
- // Using the MemPoolAccept m_view cache allows us to look up these same coins faster later.
1716
- // This should be connecting directly to CoinsTip, not to m_viewmempool, because we specifically
1717
- // require inputs to be confirmed if they aren't in the package.
1718
- m_view.SetBackend (m_active_chainstate.CoinsTip ());
1719
- const auto package_or_confirmed = [this , &unconfirmed_parent_txids](const auto & input) {
1720
- return unconfirmed_parent_txids.count (input.prevout .hash ) > 0 || m_view.HaveCoin (input.prevout );
1721
- };
1722
- if (!std::all_of (child->vin .cbegin (), child->vin .cend (), package_or_confirmed)) {
1723
- package_state_quit_early.Invalid (PackageValidationResult::PCKG_POLICY, " package-not-child-with-unconfirmed-parents" );
1724
- return PackageMempoolAcceptResult (package_state_quit_early, {});
1691
+ if (package.size () > 1 ) {
1692
+ // All transactions in the package must be a parent of the last transaction. This is just an
1693
+ // opportunity for us to fail fast on a context-free check without taking the mempool lock.
1694
+ if (!IsChildWithParents (package)) {
1695
+ package_state_quit_early.Invalid (PackageValidationResult::PCKG_POLICY, " package-not-child-with-parents" );
1696
+ return PackageMempoolAcceptResult (package_state_quit_early, {});
1697
+ }
1698
+
1699
+ // IsChildWithParents() guarantees the package is > 1 transactions.
1700
+ assert (package.size () > 1 );
1701
+ // The package must be 1 child with all of its unconfirmed parents. The package is expected to
1702
+ // be sorted, so the last transaction is the child.
1703
+ const auto & child = package.back ();
1704
+ std::unordered_set<uint256, SaltedTxidHasher> unconfirmed_parent_txids;
1705
+ std::transform (package.cbegin (), package.cend () - 1 ,
1706
+ std::inserter (unconfirmed_parent_txids, unconfirmed_parent_txids.end ()),
1707
+ [](const auto & tx) { return tx->GetHash (); });
1708
+
1709
+ // All child inputs must refer to a preceding package transaction or a confirmed UTXO. The only
1710
+ // way to verify this is to look up the child's inputs in our current coins view (not including
1711
+ // mempool), and enforce that all parents not present in the package be available at chain tip.
1712
+ // Since this check can bring new coins into the coins cache, keep track of these coins and
1713
+ // uncache them if we don't end up submitting this package to the mempool.
1714
+ const CCoinsViewCache& coins_tip_cache = m_active_chainstate.CoinsTip ();
1715
+ for (const auto & input : child->vin ) {
1716
+ if (!coins_tip_cache.HaveCoinInCache (input.prevout )) {
1717
+ args.m_coins_to_uncache .push_back (input.prevout );
1718
+ }
1719
+ }
1720
+ // Using the MemPoolAccept m_view cache allows us to look up these same coins faster later.
1721
+ // This should be connecting directly to CoinsTip, not to m_viewmempool, because we specifically
1722
+ // require inputs to be confirmed if they aren't in the package.
1723
+ m_view.SetBackend (m_active_chainstate.CoinsTip ());
1724
+ const auto package_or_confirmed = [this , &unconfirmed_parent_txids](const auto & input) {
1725
+ return unconfirmed_parent_txids.count (input.prevout .hash ) > 0 || m_view.HaveCoin (input.prevout );
1726
+ };
1727
+ if (!std::all_of (child->vin .cbegin (), child->vin .cend (), package_or_confirmed)) {
1728
+ package_state_quit_early.Invalid (PackageValidationResult::PCKG_POLICY, " package-not-child-with-unconfirmed-parents" );
1729
+ return PackageMempoolAcceptResult (package_state_quit_early, {});
1730
+ }
1731
+ // Protect against bugs where we pull more inputs from disk that miss being added to
1732
+ // coins_to_uncache. The backend will be connected again when needed in PreChecks.
1733
+ m_view.SetBackend (m_dummy);
1725
1734
}
1726
- // Protect against bugs where we pull more inputs from disk that miss being added to
1727
- // coins_to_uncache. The backend will be connected again when needed in PreChecks.
1728
- m_view.SetBackend (m_dummy);
1729
1735
1730
1736
LOCK (m_pool.cs );
1731
1737
// Stores results from which we will create the returned PackageMempoolAcceptResult.
@@ -1735,6 +1741,7 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
1735
1741
// this transaction. "Nonfinal" because if a transaction fails by itself but succeeds later
1736
1742
// (i.e. when evaluated with a fee-bumping child), the result in this map may be discarded.
1737
1743
std::map<uint256, MempoolAcceptResult> individual_results_nonfinal;
1744
+ // Tracks whether we think package submission could result in successful entry to the mempool
1738
1745
bool quit_early{false };
1739
1746
std::vector<CTransactionRef> txns_package_eval;
1740
1747
for (const auto & tx : package) {
@@ -1776,8 +1783,9 @@ PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package,
1776
1783
// in package validation, because its fees should only be "used" once.
1777
1784
assert (m_pool.exists (GenTxid::Wtxid (wtxid)));
1778
1785
results_final.emplace (wtxid, single_res);
1779
- } else if (single_res.m_state .GetResult () != TxValidationResult::TX_RECONSIDERABLE &&
1780
- single_res.m_state .GetResult () != TxValidationResult::TX_MISSING_INPUTS) {
1786
+ } else if (package.size () == 1 || // If there is only one transaction, no need to retry it "as a package"
1787
+ (single_res.m_state .GetResult () != TxValidationResult::TX_RECONSIDERABLE &&
1788
+ single_res.m_state .GetResult () != TxValidationResult::TX_MISSING_INPUTS)) {
1781
1789
// Package validation policy only differs from individual policy in its evaluation
1782
1790
// of feerate. For example, if a transaction fails here due to violation of a
1783
1791
// consensus rule, the result will not change when it is submitted as part of a
0 commit comments