| 612 | } |
| 613 | |
| 614 | void CTxMemPool::check(const CCoinsViewCache *pcoins) const |
| 615 | { |
| 616 | LOCK(cs); |
| 617 | if (nCheckFrequency == 0) |
| 618 | return; |
| 619 | |
| 620 | if (GetRand(std::numeric_limits<uint32_t>::max()) >= nCheckFrequency) |
| 621 | return; |
| 622 | |
| 623 | LogPrint(BCLog::MEMPOOL, "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size()); |
| 624 | |
| 625 | uint64_t checkTotal = 0; |
| 626 | uint64_t innerUsage = 0; |
| 627 | |
| 628 | CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins)); |
| 629 | const int64_t spendheight = GetSpendHeight(mempoolDuplicate); |
| 630 | |
| 631 | std::list<const CTxMemPoolEntry*> waitingOnDependants; |
| 632 | for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) { |
| 633 | unsigned int i = 0; |
| 634 | checkTotal += it->GetTxSize(); |
| 635 | innerUsage += it->DynamicMemoryUsage(); |
| 636 | const CTransaction& tx = it->GetTx(); |
| 637 | txlinksMap::const_iterator linksiter = mapLinks.find(it); |
| 638 | assert(linksiter != mapLinks.end()); |
| 639 | const TxLinks &links = linksiter->second; |
| 640 | innerUsage += memusage::DynamicUsage(links.parents) + memusage::DynamicUsage(links.children); |
| 641 | bool fDependsWait = false; |
| 642 | setEntries setParentCheck; |
| 643 | int64_t parentSizes = 0; |
| 644 | int64_t parentSigOpCost = 0; |
| 645 | for (const CTxIn &txin : tx.vin) { |
| 646 | // Check that every mempool transaction's inputs refer to available coins, or other mempool tx's. |
| 647 | indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash); |
| 648 | if (it2 != mapTx.end()) { |
| 649 | const CTransaction& tx2 = it2->GetTx(); |
| 650 | assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull()); |
| 651 | fDependsWait = true; |
| 652 | if (setParentCheck.insert(it2).second) { |
| 653 | parentSizes += it2->GetTxSize(); |
| 654 | parentSigOpCost += it2->GetSigOpCost(); |
| 655 | } |
| 656 | } else { |
| 657 | assert(pcoins->HaveCoin(txin.prevout)); |
| 658 | } |
| 659 | // Check whether its inputs are marked in mapNextTx. |
| 660 | auto it3 = mapNextTx.find(txin.prevout); |
| 661 | assert(it3 != mapNextTx.end()); |
| 662 | assert(it3->first == &txin.prevout); |
| 663 | assert(it3->second == &tx); |
| 664 | i++; |
| 665 | } |
| 666 | assert(setParentCheck == GetMemPoolParents(it)); |
| 667 | // Verify ancestor state is correct. |
| 668 | setEntries setAncestors; |
| 669 | uint64_t nNoLimit = std::numeric_limits<uint64_t>::max(); |
| 670 | std::string dummy; |
| 671 | CalculateMemPoolAncestors(*it, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy); |
nothing calls this directly
no test coverage detected