| 795 | } |
| 796 | |
| 797 | void CTxMemPool::check(const CBlockIndex* active_chain_tip, const CCoinsViewCache& active_coins_tip, int64_t spendheight) const |
| 798 | { |
| 799 | if (m_check_ratio == 0) return; |
| 800 | |
| 801 | if (GetRand(m_check_ratio) >= 1) return; |
| 802 | |
| 803 | AssertLockHeld(::cs_main); |
| 804 | LOCK(cs); |
| 805 | LogPrint(BCLog::MEMPOOL, "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size()); |
| 806 | |
| 807 | uint64_t checkTotal = 0; |
| 808 | CAmount check_total_fee{0}; |
| 809 | uint64_t innerUsage = 0; |
| 810 | uint64_t prev_ancestor_count{0}; |
| 811 | |
| 812 | CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(&active_coins_tip)); |
| 813 | |
| 814 | // ELEMENTS: |
| 815 | std::set<std::pair<uint256, COutPoint>> setGlobalPeginsSpent; |
| 816 | |
| 817 | for (const auto& it : GetSortedDepthAndScore()) { |
| 818 | checkTotal += it->GetTxSize(); |
| 819 | check_total_fee += it->GetFee(); |
| 820 | innerUsage += it->DynamicMemoryUsage(); |
| 821 | const CTransaction& tx = it->GetTx(); |
| 822 | innerUsage += memusage::DynamicUsage(it->GetMemPoolParentsConst()) + memusage::DynamicUsage(it->GetMemPoolChildrenConst()); |
| 823 | CTxMemPoolEntry::Parents setParentCheck; |
| 824 | for (const CTxIn &txin : tx.vin) { |
| 825 | // Check that every mempool transaction's inputs refer to available coins, or other mempool tx's. |
| 826 | indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash); |
| 827 | if (it2 != mapTx.end()) { |
| 828 | const CTransaction& tx2 = it2->GetTx(); |
| 829 | assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull()); |
| 830 | setParentCheck.insert(*it2); |
| 831 | } |
| 832 | // We are iterating through the mempool entries sorted in order by ancestor count. |
| 833 | // All parents must have been checked before their children and their coins added to |
| 834 | // the mempoolDuplicate coins cache. |
| 835 | // ELEMENTS: peg-in inputs are not sanity-checked to be valid |
| 836 | assert(mempoolDuplicate.HaveCoin(txin.prevout) || txin.m_is_pegin); |
| 837 | // Check whether its inputs are marked in mapNextTx. |
| 838 | auto it3 = mapNextTx.find(txin.prevout); |
| 839 | assert(it3 != mapNextTx.end()); |
| 840 | assert(it3->first == &txin.prevout); |
| 841 | assert(it3->second == &tx); |
| 842 | } |
| 843 | auto comp = [](const CTxMemPoolEntry& a, const CTxMemPoolEntry& b) -> bool { |
| 844 | return a.GetTx().GetHash() == b.GetTx().GetHash(); |
| 845 | }; |
| 846 | assert(setParentCheck.size() == it->GetMemPoolParentsConst().size()); |
| 847 | assert(std::equal(setParentCheck.begin(), setParentCheck.end(), it->GetMemPoolParentsConst().begin(), comp)); |
| 848 | // Verify ancestor state is correct. |
| 849 | setEntries setAncestors; |
| 850 | uint64_t nNoLimit = std::numeric_limits<uint64_t>::max(); |
| 851 | std::string dummy; |
| 852 | CalculateMemPoolAncestors(*it, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy); |
| 853 | uint64_t nCountCheck = setAncestors.size() + 1; |
| 854 | uint64_t nSizeCheck = it->GetTxSize(); |
nothing calls this directly
no test coverage detected