vHashesToUpdate is the set of transaction hashes from a disconnected block which has been re-added to the mempool. for each entry, look for descendants that are outside vHashesToUpdate, and add fee/size information for such descendants to the parent. for each such descendant, also update the ancestor state to include the parent.
| 107 | // add fee/size information for such descendants to the parent. |
| 108 | // for each such descendant, also update the ancestor state to include the parent. |
| 109 | void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashesToUpdate) |
| 110 | { |
| 111 | LOCK(cs); |
| 112 | // For each entry in vHashesToUpdate, store the set of in-mempool, but not |
| 113 | // in-vHashesToUpdate transactions, so that we don't have to recalculate |
| 114 | // descendants when we come across a previously seen entry. |
| 115 | cacheMap mapMemPoolDescendantsToUpdate; |
| 116 | |
| 117 | // Use a set for lookups into vHashesToUpdate (these entries are already |
| 118 | // accounted for in the state of their ancestors) |
| 119 | std::set<uint256> setAlreadyIncluded(vHashesToUpdate.begin(), vHashesToUpdate.end()); |
| 120 | |
| 121 | // Iterate in reverse, so that whenever we are looking at a transaction |
| 122 | // we are sure that all in-mempool descendants have already been processed. |
| 123 | // This maximizes the benefit of the descendant cache and guarantees that |
| 124 | // setMemPoolChildren will be updated, an assumption made in |
| 125 | // UpdateForDescendants. |
| 126 | for (const uint256 &hash : reverse_iterate(vHashesToUpdate)) { |
| 127 | // we cache the in-mempool children to avoid duplicate updates |
| 128 | setEntries setChildren; |
| 129 | // calculate children from mapNextTx |
| 130 | txiter it = mapTx.find(hash); |
| 131 | if (it == mapTx.end()) { |
| 132 | continue; |
| 133 | } |
| 134 | auto iter = mapNextTx.lower_bound(COutPoint(hash, 0)); |
| 135 | // First calculate the children, and update setMemPoolChildren to |
| 136 | // include them, and update their setMemPoolParents to include this tx. |
| 137 | for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) { |
| 138 | const uint256 &childHash = iter->second->GetHash(); |
| 139 | txiter childIter = mapTx.find(childHash); |
| 140 | assert(childIter != mapTx.end()); |
| 141 | // We can skip updating entries we've encountered before or that |
| 142 | // are in the block (which are already accounted for). |
| 143 | if (setChildren.insert(childIter).second && !setAlreadyIncluded.count(childHash)) { |
| 144 | UpdateChild(it, childIter, true); |
| 145 | UpdateParent(childIter, it, true); |
| 146 | } |
| 147 | } |
| 148 | UpdateForDescendants(it, mapMemPoolDescendantsToUpdate, setAlreadyIncluded); |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | bool CTxMemPool::CalculateMemPoolAncestors(const CTxMemPoolEntry &entry, setEntries &setAncestors, uint64_t limitAncestorCount, uint64_t limitAncestorSize, uint64_t limitDescendantCount, uint64_t limitDescendantSize, std::string &errString, bool fSearchForParents /* = true */) const |
| 153 | { |
no test coverage detected