| 1779 | } // anon namespace |
| 1780 | |
| 1781 | MempoolAcceptResult AcceptToMemoryPool(Chainstate& active_chainstate, const CTransactionRef& tx, |
| 1782 | int64_t accept_time, bool bypass_limits, bool test_accept) |
| 1783 | { |
| 1784 | AssertLockHeld(::cs_main); |
| 1785 | const CChainParams& chainparams{active_chainstate.m_chainman.GetParams()}; |
| 1786 | assert(active_chainstate.GetMempool() != nullptr); |
| 1787 | CTxMemPool& pool{*active_chainstate.GetMempool()}; |
| 1788 | |
| 1789 | std::vector<COutPoint> coins_to_uncache; |
| 1790 | |
| 1791 | auto args = MemPoolAccept::ATMPArgs::SingleAccept(chainparams, accept_time, bypass_limits, coins_to_uncache, test_accept); |
| 1792 | MempoolAcceptResult result = MemPoolAccept(pool, active_chainstate).AcceptSingleTransactionAndCleanup(tx, args); |
| 1793 | |
| 1794 | if (result.m_result_type != MempoolAcceptResult::ResultType::VALID) { |
| 1795 | // Remove coins that were not present in the coins cache before calling |
| 1796 | // AcceptSingleTransaction(); this is to prevent memory DoS in case we receive a large |
| 1797 | // number of invalid transactions that attempt to overrun the in-memory coins cache |
| 1798 | // (`CCoinsViewCache::cacheCoins`). |
| 1799 | |
| 1800 | for (const COutPoint& hashTx : coins_to_uncache) |
| 1801 | active_chainstate.CoinsTip().Uncache(hashTx); |
| 1802 | TRACEPOINT(mempool, rejected, |
| 1803 | tx->GetHash().data(), |
| 1804 | result.m_state.GetRejectReason().c_str() |
| 1805 | ); |
| 1806 | } |
| 1807 | // After we've (potentially) uncached entries, ensure our coins cache is still within its size limits |
| 1808 | BlockValidationState state_dummy; |
| 1809 | active_chainstate.FlushStateToDisk(state_dummy, FlushStateMode::PERIODIC); |
| 1810 | return result; |
| 1811 | } |
| 1812 | |
| 1813 | PackageMempoolAcceptResult ProcessNewPackage(Chainstate& active_chainstate, CTxMemPool& pool, |
| 1814 | const Package& package, bool test_accept, const std::optional<CFeeRate>& client_maxfeerate) |