| 1626 | } |
| 1627 | |
| 1628 | PackageMempoolAcceptResult MemPoolAccept::AcceptPackage(const Package& package, ATMPArgs& args) |
| 1629 | { |
| 1630 | Assert(!package.empty()); |
| 1631 | AssertLockHeld(cs_main); |
| 1632 | // Used if returning a PackageMempoolAcceptResult directly from this function. |
| 1633 | PackageValidationState package_state_quit_early; |
| 1634 | |
| 1635 | // There are two topologies we are able to handle through this function: |
| 1636 | // (1) A single transaction |
| 1637 | // (2) A child-with-parents package. |
| 1638 | // Check that the package is well-formed. If it isn't, we won't try to validate any of the |
| 1639 | // transactions and thus won't return any MempoolAcceptResults, just a package-wide error. |
| 1640 | |
| 1641 | // Context-free package checks. |
| 1642 | if (!IsWellFormedPackage(package, package_state_quit_early)) { |
| 1643 | return PackageMempoolAcceptResult(package_state_quit_early, {}); |
| 1644 | } |
| 1645 | |
| 1646 | if (package.size() > 1 && !IsChildWithParents(package)) { |
| 1647 | // All transactions in the package must be a parent of the last transaction. This is just an |
| 1648 | // opportunity for us to fail fast on a context-free check without taking the mempool lock. |
| 1649 | package_state_quit_early.Invalid(PackageValidationResult::PCKG_POLICY, "package-not-child-with-parents"); |
| 1650 | return PackageMempoolAcceptResult(package_state_quit_early, {}); |
| 1651 | } |
| 1652 | |
| 1653 | LOCK(m_pool.cs); |
| 1654 | // Stores results from which we will create the returned PackageMempoolAcceptResult. |
| 1655 | // A result may be changed if a mempool transaction is evicted later due to LimitMempoolSize(). |
| 1656 | std::map<Wtxid, MempoolAcceptResult> results_final; |
| 1657 | // Results from individual validation which will be returned if no other result is available for |
| 1658 | // this transaction. "Nonfinal" because if a transaction fails by itself but succeeds later |
| 1659 | // (i.e. when evaluated with a fee-bumping child), the result in this map may be discarded. |
| 1660 | std::map<Wtxid, MempoolAcceptResult> individual_results_nonfinal; |
| 1661 | // Tracks whether we think package submission could result in successful entry to the mempool |
| 1662 | bool quit_early{false}; |
| 1663 | std::vector<CTransactionRef> txns_package_eval; |
| 1664 | for (const auto& tx : package) { |
| 1665 | const auto& wtxid = tx->GetWitnessHash(); |
| 1666 | const auto& txid = tx->GetHash(); |
| 1667 | // There are 3 possibilities: already in mempool, same-txid-diff-wtxid already in mempool, |
| 1668 | // or not in mempool. An already confirmed tx is treated as one not in mempool, because all |
| 1669 | // we know is that the inputs aren't available. |
| 1670 | if (m_pool.exists(wtxid)) { |
| 1671 | // Exact transaction already exists in the mempool. |
| 1672 | // Node operators are free to set their mempool policies however they please, nodes may receive |
| 1673 | // transactions in different orders, and malicious counterparties may try to take advantage of |
| 1674 | // policy differences to pin or delay propagation of transactions. As such, it's possible for |
| 1675 | // some package transaction(s) to already be in the mempool, and we don't want to reject the |
| 1676 | // entire package in that case (as that could be a censorship vector). De-duplicate the |
| 1677 | // transactions that are already in the mempool, and only call AcceptMultipleTransactions() with |
| 1678 | // the new transactions. This ensures we don't double-count transaction counts and sizes when |
| 1679 | // checking ancestor/descendant limits, or double-count transaction fees for fee-related policy. |
| 1680 | const auto& entry{*Assert(m_pool.GetEntry(txid))}; |
| 1681 | results_final.emplace(wtxid, MempoolAcceptResult::MempoolTx(entry.GetTxSize(), entry.GetFee())); |
| 1682 | } else if (m_pool.exists(txid)) { |
| 1683 | // Transaction with the same non-witness data but different witness (same txid, |
| 1684 | // different wtxid) already exists in the mempool. |
| 1685 | // |
no test coverage detected