Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2014 The Bitcoin developers
3 : // Copyright (c) 2016-2021 The PIVX Core developers
4 : // Distributed under the MIT software license, see the accompanying
5 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 :
7 : #include "txmempool.h"
8 :
9 : #include "clientversion.h"
10 : #include "bls/bls_wrapper.h"
11 : #include "evo/deterministicmns.h"
12 : #include "evo/specialtx_validation.h"
13 : #include "evo/providertx.h"
14 : #include "policy/fees.h"
15 : #include "reverse_iterate.h"
16 : #include "streams.h"
17 : #include "timedata.h"
18 : #include "util/system.h"
19 : #include "utilmoneystr.h"
20 : #include "utiltime.h"
21 : #include "version.h"
22 : #include "validation.h"
23 : #include "validationinterface.h"
24 :
25 :
26 170052 : CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee,
27 : int64_t _nTime, unsigned int _entryHeight,
28 170052 : bool _spendsCoinbaseOrCoinstake, unsigned int _sigOps) :
29 170052 : tx(MakeTransactionRef(_tx)), nFee(_nFee), nTime(_nTime), entryHeight(_entryHeight),
30 170052 : spendsCoinbaseOrCoinstake(_spendsCoinbaseOrCoinstake), sigOpCount(_sigOps)
31 : {
32 170052 : nTxSize = ::GetSerializeSize(*_tx, PROTOCOL_VERSION);
33 170052 : nUsageSize = _tx->DynamicMemoryUsage();
34 170052 : hasZerocoins = _tx->ContainsZerocoins();
35 170052 : m_isShielded = _tx->IsShieldedTx();
36 :
37 170052 : nCountWithDescendants = 1;
38 170052 : nSizeWithDescendants = nTxSize;
39 170052 : nModFeesWithDescendants = nFee;
40 :
41 170052 : feeDelta = 0;
42 :
43 170052 : nCountWithAncestors = 1;
44 170052 : nSizeWithAncestors = nTxSize;
45 170052 : nModFeesWithAncestors = nFee;
46 170052 : nSigOpCountWithAncestors = sigOpCount;
47 170052 : }
48 :
49 2 : void CTxMemPoolEntry::UpdateFeeDelta(int64_t newFeeDelta)
50 : {
51 2 : nModFeesWithDescendants += newFeeDelta - feeDelta;
52 2 : nModFeesWithAncestors += newFeeDelta - feeDelta;
53 2 : feeDelta = newFeeDelta;
54 2 : }
55 :
56 : // Update the given tx for any in-mempool descendants.
57 : // Assumes that setMemPoolChildren is correct for the given tx and all
58 : // descendants.
59 27766 : void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendants, const std::set<uint256> &setExclude)
60 : {
61 55532 : setEntries stageEntries, setAllDescendants;
62 27766 : stageEntries = GetMemPoolChildren(updateIt);
63 :
64 90592 : while (!stageEntries.empty()) {
65 62826 : const txiter cit = *stageEntries.begin();
66 62826 : setAllDescendants.insert(cit);
67 62826 : stageEntries.erase(cit);
68 62826 : const setEntries &setChildren = GetMemPoolChildren(cit);
69 96339 : for (const txiter& childEntry : setChildren) {
70 33513 : cacheMap::iterator cacheIt = cachedDescendants.find(childEntry);
71 33513 : if (cacheIt != cachedDescendants.end()) {
72 : // We've already calculated this one, just add the entries for this set
73 : // but don't traverse again.
74 13375 : for (const txiter& cacheEntry : cacheIt->second) {
75 7536 : setAllDescendants.insert(cacheEntry);
76 : }
77 27680 : } else if (!setAllDescendants.count(childEntry)) {
78 : // Schedule for later processing
79 61181 : stageEntries.insert(childEntry);
80 : }
81 : }
82 : }
83 : // setAllDescendants now contains all in-mempool descendants of updateIt.
84 : // Update and add to cached descendant map
85 27766 : int64_t modifySize = 0;
86 27766 : CAmount modifyFee = 0;
87 27766 : int64_t modifyCount = 0;
88 98118 : for (const txiter& cit : setAllDescendants) {
89 114770 : if (!setExclude.count(cit->GetTx().GetHash())) {
90 25934 : modifySize += cit->GetTxSize();
91 25934 : modifyFee += cit->GetModifiedFee();
92 25934 : modifyCount++;
93 25934 : cachedDescendants[updateIt].insert(cit);
94 : // Update ancestor state for each descendant
95 25934 : mapTx.modify(cit, update_ancestor_state(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCount()));
96 : }
97 : }
98 27766 : mapTx.modify(updateIt, update_descendant_state(modifySize, modifyFee, modifyCount));
99 27766 : }
100 :
101 : // vHashesToUpdate is the set of transaction hashes from a disconnected block
102 : // which has been re-added to the mempool.
103 : // for each entry, look for descendants that are outside hashesToUpdate, and
104 : // add fee/size information for such descendants to the parent.
105 : // for each such descendant, also update the ancestor state to include the parent.
106 63 : void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashesToUpdate)
107 : {
108 63 : LOCK(cs);
109 : // For each entry in vHashesToUpdate, store the set of in-mempool, but not
110 : // in-vHashesToUpdate transactions, so that we don't have to recalculate
111 : // descendants when we come across a previously seen entry.
112 126 : cacheMap mapMemPoolDescendantsToUpdate;
113 :
114 : // Use a set for lookups into vHashesToUpdate (these entries are already
115 : // accounted for in the state of their ancestors)
116 126 : std::set<uint256> setAlreadyIncluded(vHashesToUpdate.begin(), vHashesToUpdate.end());
117 :
118 : // Iterate in reverse, so that whenever we are looking at at a transaction
119 : // we are sure that all in-mempool descendants have already been processed.
120 : // This maximizes the benefit of the descendant cache and guarantees that
121 : // setMemPoolChildren will be updated, an assumption made in
122 : // UpdateForDescendants.
123 27829 : for (const uint256 &hash : reverse_iterate(vHashesToUpdate)) {
124 : // we cache the in-mempool children to avoid duplicate updates
125 55532 : setEntries setChildren;
126 : // calculate children from mapNextTx
127 27766 : txiter it = mapTx.find(hash);
128 27766 : if (it == mapTx.end()) {
129 0 : continue;
130 : }
131 27766 : auto iter = mapNextTx.lower_bound(COutPoint(hash, 0));
132 : // First calculate the children, and update setMemPoolChildren to
133 : // include them, and update their setMemPoolParents to include this tx.
134 62928 : for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) {
135 35162 : const uint256 &childHash = iter->second->GetHash();
136 35162 : txiter childIter = mapTx.find(childHash);
137 35162 : assert(childIter != mapTx.end());
138 : // We can skip updating entries we've encountered before or that
139 : // are in the block (which are already accounted for).
140 60646 : if (setChildren.insert(childIter).second && !setAlreadyIncluded.count(childHash)) {
141 9677 : UpdateChild(it, childIter, true);
142 9677 : UpdateParent(childIter, it, true);
143 : }
144 : }
145 27766 : UpdateForDescendants(it, mapMemPoolDescendantsToUpdate, setAlreadyIncluded);
146 : }
147 63 : }
148 :
149 2976214 : 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
150 : {
151 5952418 : setEntries parentHashes;
152 5952418 : const auto &tx = entry.GetSharedTx();
153 :
154 2976214 : if (fSearchForParents) {
155 : // Get parents of this transaction that are in the mempool
156 : // GetMemPoolParents() is only valid for entries in the mempool, so we
157 : // iterate mapTx to find parents.
158 6445589 : for (unsigned int i = 0; i < tx->vin.size(); i++) {
159 3754228 : txiter piter = mapTx.find(tx->vin[i].prevout.hash);
160 3754228 : if (piter != mapTx.end()) {
161 55483 : parentHashes.insert(piter);
162 55483 : if (parentHashes.size() + 1 > limitAncestorCount) {
163 0 : errString = strprintf("too many unconfirmed parents [limit: %u]", limitAncestorCount);
164 0 : return false;
165 : }
166 : }
167 : }
168 : } else {
169 : // If we're not searching for parents, we require this to be an
170 : // entry in the mempool already.
171 284846 : txiter it = mapTx.iterator_to(entry);
172 284846 : parentHashes = GetMemPoolParents(it);
173 : }
174 :
175 2976214 : size_t totalSizeWithAncestors = entry.GetTxSize();
176 :
177 5681880 : while (!parentHashes.empty()) {
178 2708252 : txiter stageit = *parentHashes.begin();
179 :
180 2708252 : setAncestors.insert(stageit);
181 2708252 : parentHashes.erase(stageit);
182 2708252 : totalSizeWithAncestors += stageit->GetTxSize();
183 :
184 2708252 : if (stageit->GetSizeWithDescendants() + entry.GetTxSize() > limitDescendantSize) {
185 0 : errString = strprintf("exceeds descendant size limit for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limitDescendantSize);
186 2583 : return false;
187 2708252 : } else if (stageit->GetCountWithDescendants() + 1 > limitDescendantCount) {
188 2578 : errString = strprintf("too many descendants for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limitDescendantCount);
189 2578 : return false;
190 2705674 : } else if (totalSizeWithAncestors > limitAncestorSize) {
191 0 : errString = strprintf("exceeds ancestor size limit [limit: %u]", limitAncestorSize);
192 0 : return false;
193 : }
194 :
195 2705674 : const setEntries & setMemPoolParents = GetMemPoolParents(stageit);
196 5343827 : for (const txiter& phash : setMemPoolParents) {
197 : // If this is a new ancestor, add it.
198 2638203 : if (setAncestors.count(phash) == 0) {
199 2638113 : parentHashes.insert(phash);
200 : }
201 2638158 : if (parentHashes.size() + setAncestors.size() + 1 > limitAncestorCount) {
202 5 : errString = strprintf("too many unconfirmed ancestors [limit: %u]", limitAncestorCount);
203 5 : return false;
204 : }
205 : }
206 : }
207 :
208 : return true;
209 : }
210 :
211 329774 : void CTxMemPool::UpdateAncestorsOf(bool add, txiter it, setEntries &setAncestors)
212 : {
213 329774 : setEntries parentIters = GetMemPoolParents(it);
214 : // add or remove this tx as a child of each parent
215 358642 : for (const txiter& piter : parentIters) {
216 28868 : UpdateChild(piter, it, add);
217 : }
218 329774 : const int64_t updateCount = (add ? 1 : -1);
219 329774 : const int64_t updateSize = updateCount * it->GetTxSize();
220 329774 : const CAmount updateFee = updateCount * it->GetModifiedFee();
221 2913652 : for (const txiter& ancestorIt : setAncestors) {
222 2583884 : mapTx.modify(ancestorIt, update_descendant_state(updateSize, updateFee, updateCount));
223 : }
224 329774 : }
225 :
226 166945 : void CTxMemPool::UpdateEntryForAncestors(txiter it, const setEntries &setAncestors)
227 : {
228 166945 : int64_t updateCount = setAncestors.size();
229 166945 : int64_t updateSize = 0;
230 166945 : CAmount updateFee = 0;
231 166945 : int updateSigOps = 0;
232 2750787 : for (const txiter& ancestorIt : setAncestors) {
233 2583842 : updateSize += ancestorIt->GetTxSize();
234 2583842 : updateFee += ancestorIt->GetModifiedFee();
235 2583842 : updateSigOps += ancestorIt->GetSigOpCount();
236 : }
237 166945 : mapTx.modify(it, update_ancestor_state(updateSize, updateFee, updateCount, updateSigOps));
238 166945 : }
239 :
240 162829 : void CTxMemPool::UpdateChildrenForRemoval(txiter it)
241 : {
242 162829 : const setEntries &setMemPoolChildren = GetMemPoolChildren(it);
243 198069 : for (const txiter& updateIt : setMemPoolChildren) {
244 35240 : UpdateParent(updateIt, it, false);
245 : }
246 162829 : }
247 :
248 293025 : void CTxMemPool::UpdateForRemoveFromMempool(const setEntries &entriesToRemove, bool updateDescendants)
249 : {
250 : // For each entry, walk back all ancestors and decrement size associated with this
251 : // transaction
252 293025 : const uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
253 293025 : if (updateDescendants) {
254 : // updateDescendants should be true whenever we're not recursively
255 : // removing a tx and all its descendants, eg when a transaction is
256 : // confirmed in a block.
257 : // Here we only update statistics and not data in mapLinks (which
258 : // we need to preserve until we're finished with all operations that
259 : // need to traverse the mempool).
260 322894 : for (const txiter& removeIt : entriesToRemove) {
261 322894 : setEntries setDescendants;
262 161447 : CalculateDescendants(removeIt, setDescendants);
263 161447 : setDescendants.erase(removeIt); // don't update state for self
264 161447 : int64_t modifySize = -((int64_t)removeIt->GetTxSize());
265 161447 : CAmount modifyFee = -removeIt->GetModifiedFee();
266 161447 : int modifySigOps = -removeIt->GetSigOpCount();
267 246573 : for (const txiter& dit : setDescendants) {
268 85126 : mapTx.modify(dit, update_ancestor_state(modifySize, modifyFee, -1, modifySigOps));
269 : }
270 : }
271 : }
272 455854 : for (const txiter& removeIt : entriesToRemove) {
273 325658 : setEntries setAncestors;
274 162829 : const CTxMemPoolEntry &entry = *removeIt;
275 325658 : std::string dummy;
276 : // Since this is a tx that is already in the mempool, we can call CMPA
277 : // with fSearchForParents = false. If the mempool is in a consistent
278 : // state, then using true or false should both be correct, though false
279 : // should be a bit faster.
280 : // However, if we happen to be in the middle of processing a reorg, then
281 : // the mempool can be in an inconsistent state. In this case, the set
282 : // of ancestors reachable via mapLinks will be the same as the set of
283 : // ancestors whose packages include this transaction, because when we
284 : // add a new transaction to the mempool in addUnchecked(), we assume it
285 : // has no children, and in the case of a reorg where that assumption is
286 : // false, the in-mempool children aren't linked to the in-block tx's
287 : // until UpdateTransactionsFromBlock() is called.
288 : // So if we're being called during a reorg, ie before
289 : // UpdateTransactionsFromBlock() has been called, then mapLinks[] will
290 : // differ from the set of mempool parents we'd calculate by searching,
291 : // and it's important that we use the mapLinks[] notion of ancestor
292 : // transactions as the set of things to update for removal.
293 162829 : CalculateMemPoolAncestors(entry, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
294 : // Note that UpdateAncestorsOf severs the child links that point to
295 : // removeIt in the entries for the parents of removeIt.
296 162829 : UpdateAncestorsOf(false, removeIt, setAncestors);
297 : }
298 : // After updating all the ancestor sizes, we can now sever the link between each
299 : // transaction being removed and any mempool children (ie, update setMemPoolParents
300 : // for each direct child of a transaction being removed).
301 455854 : for (const txiter& removeIt : entriesToRemove) {
302 162829 : UpdateChildrenForRemoval(removeIt);
303 : }
304 293025 : }
305 :
306 2611671 : void CTxMemPoolEntry::UpdateDescendantState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount)
307 : {
308 2611671 : nSizeWithDescendants += modifySize;
309 2611671 : assert(int64_t(nSizeWithDescendants) > 0);
310 2611671 : nModFeesWithDescendants += modifyFee;
311 2611671 : nCountWithDescendants += modifyCount;
312 2611671 : assert(int64_t(nCountWithDescendants) > 0);
313 2611671 : }
314 :
315 278005 : void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int modifySigOps)
316 : {
317 278005 : nSizeWithAncestors += modifySize;
318 278005 : assert(int64_t(nSizeWithAncestors) > 0);
319 278005 : nModFeesWithAncestors += modifyFee;
320 278005 : nCountWithAncestors += modifyCount;
321 278005 : assert(int64_t(nCountWithAncestors) > 0);
322 278005 : nSigOpCountWithAncestors += modifySigOps;
323 278005 : assert(int(nSigOpCountWithAncestors) >= 0);
324 278005 : }
325 :
326 484 : CTxMemPool::CTxMemPool(const CFeeRate& _minReasonableRelayFee) :
327 484 : nTransactionsUpdated(0)
328 : {
329 484 : _clear(); // lock-free clear
330 :
331 : // Sanity checks off by default for performance, because otherwise
332 : // accepting transactions becomes O(N^2) where N is the number
333 : // of transactions in the pool
334 484 : nCheckFrequency = 0;
335 :
336 484 : minerPolicyEstimator = new CBlockPolicyEstimator(_minReasonableRelayFee);
337 484 : minReasonableRelayFee = _minReasonableRelayFee;
338 484 : }
339 :
340 484 : CTxMemPool::~CTxMemPool()
341 : {
342 968 : delete minerPolicyEstimator;
343 484 : }
344 :
345 18 : bool CTxMemPool::isSpent(const COutPoint& outpoint)
346 : {
347 18 : LOCK(cs);
348 36 : return mapNextTx.count(outpoint);
349 : }
350 :
351 0 : unsigned int CTxMemPool::GetTransactionsUpdated() const
352 : {
353 0 : LOCK(cs);
354 0 : return nTransactionsUpdated;
355 : }
356 :
357 41907 : void CTxMemPool::AddTransactionsUpdated(unsigned int n)
358 : {
359 41907 : LOCK(cs);
360 41907 : nTransactionsUpdated += n;
361 41907 : }
362 :
363 166945 : void CTxMemPool::addUncheckedSpecialTx(const CTransaction& tx)
364 : {
365 169125 : if (!tx.IsSpecialTx()) return;
366 :
367 : // Invalid special txes never get this far because transactions should be
368 : // fully checked by AcceptToMemoryPool() at this point, so we just assume that
369 : // everything is fine here.
370 357 : const uint256& txid = tx.GetHash();
371 357 : switch(tx.nType) {
372 324 : case CTransaction::TxType::PROREG: {
373 324 : ProRegPL pl;
374 324 : bool ok = GetTxPayload(tx, pl);
375 324 : assert(ok);
376 4864 : if (!pl.collateralOutpoint.hash.IsNull()) {
377 188 : mapProTxRefs.emplace(txid, pl.collateralOutpoint.hash);
378 188 : mapProTxCollaterals.emplace(pl.collateralOutpoint, txid);
379 : }
380 324 : mapProTxAddresses.emplace(pl.addr, txid);
381 324 : mapProTxPubKeyIDs.emplace(pl.keyIDOwner, txid);
382 324 : mapProTxBlsPubKeyHashes.emplace(pl.pubKeyOperator.GetHash(), txid);
383 324 : break;
384 : }
385 :
386 7 : case CTransaction::TxType::PROUPSERV: {
387 7 : ProUpServPL pl;
388 7 : bool ok = GetTxPayload(tx, pl);
389 7 : assert(ok);
390 7 : mapProTxRefs.emplace(pl.proTxHash, txid);
391 7 : mapProTxAddresses.emplace(pl.addr, txid);
392 7 : break;
393 : }
394 :
395 18 : case CTransaction::TxType::PROUPREG: {
396 18 : ProUpRegPL pl;
397 18 : bool ok = GetTxPayload(tx, pl);
398 18 : assert(ok);
399 18 : mapProTxRefs.emplace(pl.proTxHash, txid);
400 18 : mapProTxBlsPubKeyHashes.emplace(pl.pubKeyOperator.GetHash(), txid);
401 18 : break;
402 : }
403 :
404 8 : case CTransaction::TxType::PROUPREV: {
405 8 : ProUpRevPL pl;
406 8 : bool ok = GetTxPayload(tx, pl);
407 8 : assert(ok);
408 8 : mapProTxRefs.emplace(pl.proTxHash, txid);
409 8 : break;
410 : }
411 :
412 : }
413 : }
414 :
415 166945 : bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, setEntries &setAncestors, bool validFeeEstimate)
416 : {
417 : // Add to memory pool without checking anything.
418 : // Used by AcceptToMemoryPool(), which DOES do all the appropriate checks.
419 166945 : LOCK(cs);
420 166945 : indexed_transaction_set::iterator newit = mapTx.insert(entry).first;
421 166945 : mapLinks.insert(make_pair(newit, TxLinks()));
422 :
423 : // Update transaction for any feeDelta created by PrioritiseTransaction
424 : // TODO: refactor so that the fee delta is calculated before inserting
425 : // into mapTx.
426 166945 : std::map<uint256, CAmount>::const_iterator pos = mapDeltas.find(hash);
427 166945 : if (pos != mapDeltas.end()) {
428 1 : const CAmount &delta = pos->second;
429 1 : if (delta) {
430 1 : mapTx.modify(newit, update_fee_delta(delta));
431 : }
432 : }
433 :
434 : // Update cachedInnerUsage to include contained transaction's usage.
435 : // (When we update the entry for in-mempool parents, memory usage will be
436 : // further updated.)
437 166945 : cachedInnerUsage += entry.DynamicMemoryUsage();
438 :
439 166945 : const CTransaction& tx = newit->GetTx();
440 333890 : std::set<uint256> setParentTransactions;
441 166945 : if(!tx.HasZerocoinSpendInputs()) {
442 466936 : for (unsigned int i = 0; i < tx.vin.size(); i++) {
443 599982 : mapNextTx.insert(std::make_pair(&tx.vin[i].prevout, newit->GetSharedTx()));
444 299991 : setParentTransactions.insert(tx.vin[i].prevout.hash);
445 : }
446 : }
447 : // Don't bother worrying about child transactions of this one.
448 : // Normal case of a new transaction arriving is that there can't be any
449 : // children, because such children would be orphans.
450 : // An exception to that is if a transaction enters that used to be in a block.
451 : // In that case, our disconnect block logic will call UpdateTransactionsFromBlock
452 : // to clean up the mess we're leaving here.
453 :
454 : // Update ancestors with information about this tx
455 466920 : for (const uint256& phash : setParentTransactions) {
456 299975 : txiter pit = mapTx.find(phash);
457 299975 : if (pit != mapTx.end()) {
458 28846 : UpdateParent(newit, pit, true);
459 : }
460 : }
461 166945 : UpdateAncestorsOf(true, newit, setAncestors);
462 166945 : UpdateEntryForAncestors(newit, setAncestors);
463 :
464 : // Save spent nullifiers
465 166945 : if (tx.IsShieldedTx()) {
466 2315 : for (const SpendDescription& sd : tx.sapData->vShieldedSpend) {
467 137 : mapSaplingNullifiers[sd.nullifier] = newit->GetSharedTx();
468 : }
469 : }
470 :
471 166945 : nTransactionsUpdated++;
472 166945 : totalTxSize += entry.GetTxSize();
473 166945 : minerPolicyEstimator->processTransaction(entry, validFeeEstimate);
474 :
475 166945 : addUncheckedSpecialTx(tx);
476 :
477 333890 : return true;
478 : }
479 :
480 162829 : void CTxMemPool::removeUncheckedSpecialTx(const CTransaction& tx)
481 : {
482 164236 : if (!tx.IsSpecialTx()) return;
483 :
484 714 : auto eraseProTxRef = [&](const uint256& proTxHash, const uint256& txHash) {
485 357 : auto its = mapProTxRefs.equal_range(proTxHash);
486 357 : for (auto it = its.first; it != its.second;) {
487 224 : if (it->second == txHash) {
488 221 : it = mapProTxRefs.erase(it);
489 : } else {
490 584 : ++it;
491 : }
492 : }
493 714 : };
494 :
495 357 : const uint256& txid = tx.GetHash();
496 357 : switch(tx.nType) {
497 324 : case CTransaction::TxType::PROREG: {
498 324 : ProRegPL pl;
499 324 : bool ok = GetTxPayload(tx, pl);
500 324 : assert(ok);
501 4676 : if (!pl.collateralOutpoint.IsNull()) {
502 324 : eraseProTxRef(txid, pl.collateralOutpoint.hash);
503 : }
504 324 : mapProTxCollaterals.erase(pl.collateralOutpoint);
505 324 : mapProTxAddresses.erase(pl.addr);
506 324 : mapProTxPubKeyIDs.erase(pl.keyIDOwner);
507 324 : mapProTxBlsPubKeyHashes.erase(pl.pubKeyOperator.GetHash());
508 324 : break;
509 : }
510 :
511 7 : case CTransaction::TxType::PROUPSERV: {
512 7 : ProUpServPL pl;
513 7 : bool ok = GetTxPayload(tx, pl);
514 7 : assert(ok);
515 7 : eraseProTxRef(pl.proTxHash, txid);
516 7 : mapProTxAddresses.erase(pl.addr);
517 7 : break;
518 : }
519 :
520 18 : case CTransaction::TxType::PROUPREG: {
521 18 : ProUpRegPL pl;
522 18 : bool ok = GetTxPayload(tx, pl);
523 18 : assert(ok);
524 18 : eraseProTxRef(pl.proTxHash, txid);
525 18 : mapProTxBlsPubKeyHashes.erase(pl.pubKeyOperator.GetHash());
526 18 : break;
527 : }
528 :
529 8 : case CTransaction::TxType::PROUPREV: {
530 8 : ProUpRevPL pl;
531 8 : bool ok = GetTxPayload(tx, pl);
532 8 : assert(ok);
533 8 : eraseProTxRef(pl.proTxHash, txid);
534 8 : break;
535 : }
536 :
537 : }
538 : }
539 :
540 162829 : void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason)
541 : {
542 162829 : if (reason != MemPoolRemovalReason::BLOCK) {
543 : // Notify clients that a transaction has been removed from the mempool
544 : // for any reason except being included in a block. Clients interested
545 : // in transactions included in blocks can subscribe to the BlockConnected
546 : // notification.
547 2764 : GetMainSignals().TransactionRemovedFromMempool(it->GetSharedTx(), reason);
548 : }
549 :
550 162829 : AssertLockHeld(cs);
551 162829 : const CTransaction& tx = it->GetTx();
552 458705 : for (const CTxIn& txin : tx.vin)
553 295876 : mapNextTx.erase(txin.prevout);
554 : // Remove spent nullifiers
555 162829 : if (tx.IsShieldedTx()) {
556 1538 : for (const SpendDescription& sd : tx.sapData->vShieldedSpend) {
557 133 : mapSaplingNullifiers.erase(sd.nullifier);
558 : }
559 : }
560 :
561 162829 : removeUncheckedSpecialTx(tx);
562 :
563 162829 : totalTxSize -= it->GetTxSize();
564 162829 : cachedInnerUsage -= it->DynamicMemoryUsage();
565 162829 : cachedInnerUsage -= memusage::DynamicUsage(mapLinks[it].parents) + memusage::DynamicUsage(mapLinks[it].children);
566 162829 : mapLinks.erase(it);
567 162829 : mapTx.erase(it);
568 162829 : nTransactionsUpdated++;
569 162829 : minerPolicyEstimator->removeTx(tx.GetHash());
570 162829 : }
571 :
572 : // Calculates descendants of entry that are not already in setDescendants, and adds to
573 : // setDescendants. Assumes entryit is already a tx in the mempool and setMemPoolChildren
574 : // is correct for tx and all descendants.
575 : // Also assumes that if an entry is in setDescendants already, then all
576 : // in-mempool descendants of it are already in setDescendants as well, so that we
577 : // can save time by not iterating over those entries.
578 302240 : void CTxMemPool::CalculateDescendants(txiter entryit, setEntries &setDescendants)
579 : {
580 302240 : setEntries stage;
581 302240 : if (setDescendants.count(entryit) == 0) {
582 302240 : stage.insert(entryit);
583 : }
584 : // Traverse down the children of entry, only adding children that are not
585 : // accounted for in setDescendants already (because those children have either
586 : // already been walked, or will be walked in this iteration).
587 3289882 : while (!stage.empty()) {
588 2987643 : txiter it = *stage.begin();
589 2987643 : setDescendants.insert(it);
590 2987643 : stage.erase(it);
591 :
592 2987643 : const setEntries &setChildren = GetMemPoolChildren(it);
593 5673091 : for (const txiter& childiter : setChildren) {
594 2685476 : if (!setDescendants.count(childiter)) {
595 5370868 : stage.insert(childiter);
596 : }
597 : }
598 : }
599 302240 : }
600 :
601 12150 : void CTxMemPool::removeRecursive(const CTransaction& origTx, MemPoolRemovalReason reason)
602 : {
603 : // Remove transaction from memory pool
604 12150 : {
605 12150 : LOCK(cs);
606 24300 : setEntries txToRemove;
607 12150 : txiter origit = mapTx.find(origTx.GetHash());
608 12150 : if (origit != mapTx.end()) {
609 15 : txToRemove.insert(origit);
610 : } else {
611 : // When recursively removing but origTx isn't in the mempool
612 : // be sure to remove any children that are in the pool. This can
613 : // happen during chain re-orgs if origTx isn't re-accepted into
614 : // the mempool for any reason.
615 34519 : for (unsigned int i = 0; i < origTx.vout.size(); i++) {
616 22384 : auto it = mapNextTx.find(COutPoint(origTx.GetHash(), i));
617 22384 : if (it == mapNextTx.end())
618 21037 : continue;
619 1347 : txiter nextit = mapTx.find(it->second->GetHash());
620 1347 : assert(nextit != mapTx.end());
621 1347 : txToRemove.insert(nextit);
622 : }
623 : }
624 24300 : setEntries setAllRemoves;
625 13512 : for (const txiter& it : txToRemove) {
626 1362 : CalculateDescendants(it, setAllRemoves);
627 : }
628 :
629 12150 : RemoveStaged(setAllRemoves, false, reason);
630 : }
631 12150 : }
632 :
633 63 : void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags)
634 : {
635 63 : AssertLockHeld(cs_main);
636 : // Remove transactions spending a coinbase which are now immature and no-longer-final transactions
637 63 : LOCK(cs);
638 126 : setEntries txToRemove;
639 34075 : for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
640 67898 : const CTransactionRef& tx = it->GetSharedTx();
641 33949 : if (!CheckFinalTx(tx, flags)) {
642 33949 : txToRemove.insert(it);
643 33949 : } else if (it->GetSpendsCoinbaseOrCoinstake()) {
644 65 : for (const CTxIn& txin : tx->vin) {
645 36 : indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
646 36 : if (it2 != mapTx.end())
647 1 : continue;
648 35 : const Coin &coin = pcoins->AccessCoin(txin.prevout);
649 35 : if (nCheckFrequency != 0) assert(!coin.IsSpent());
650 35 : if (coin.IsSpent() || ((coin.IsCoinBase() || coin.IsCoinStake()) && ((signed long)nMemPoolHeight) - coin.nHeight < (signed long)Params().GetConsensus().nCoinbaseMaturity)) {
651 3 : txToRemove.insert(it);
652 3 : break;
653 : }
654 : }
655 : }
656 : }
657 126 : setEntries setAllRemoves;
658 66 : for (txiter it : txToRemove) {
659 3 : CalculateDescendants(it, setAllRemoves);
660 : }
661 63 : RemoveStaged(setAllRemoves, false, MemPoolRemovalReason::REORG);
662 63 : }
663 :
664 4 : void CTxMemPool::removeWithAnchor(const uint256& invalidRoot)
665 : {
666 :
667 : // If a block is disconnected from the tip, and the root changed,
668 : // we must invalidate transactions from the mempool which spend
669 : // from that root -- almost as though they were spending coinbases
670 : // which are no longer valid to spend due to coinbase maturity.
671 4 : LOCK(cs);
672 8 : std::list<CTransaction> transactionsToRemove;
673 10 : for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
674 1 : const CTransaction& tx = it->GetTx();
675 1 : if (!tx.IsShieldedTx()) continue;
676 1 : for (const auto& sd : tx.sapData->vShieldedSpend) {
677 1 : if (sd.anchor == invalidRoot) {
678 2 : transactionsToRemove.emplace_back(tx);
679 : break;
680 : }
681 : }
682 : }
683 5 : for (const CTransaction& tx : transactionsToRemove) {
684 1 : removeRecursive(tx);
685 : }
686 4 : }
687 :
688 252677 : void CTxMemPool::removeConflicts(const CTransaction& tx)
689 : {
690 : // Remove transactions which depend on inputs of tx, recursively
691 252677 : std::list<CTransaction> result;
692 505354 : LOCK(cs);
693 649442 : for (const CTxIn& txin : tx.vin) {
694 396765 : auto it = mapNextTx.find(txin.prevout);
695 396765 : if (it != mapNextTx.end()) {
696 0 : const CTransaction& txConflict = *it->second;
697 0 : if (txConflict != tx) {
698 0 : removeRecursive(txConflict, MemPoolRemovalReason::CONFLICT);
699 0 : ClearPrioritisation(txConflict.GetHash());
700 : }
701 : }
702 : }
703 : // Remove txes with conflicting nullifier
704 256807 : if (tx.IsShieldedTx()) {
705 1608 : for (const SpendDescription& sd : tx.sapData->vShieldedSpend) {
706 149 : const auto& it = mapSaplingNullifiers.find(sd.nullifier);
707 149 : if (it != mapSaplingNullifiers.end()) {
708 0 : const CTransaction& txConflict = *it->second;
709 0 : if (txConflict != tx) {
710 0 : removeRecursive(txConflict, MemPoolRemovalReason::CONFLICT);
711 0 : ClearPrioritisation(txConflict.GetHash());
712 : }
713 : }
714 : }
715 : }
716 252677 : }
717 :
718 403 : void CTxMemPool::removeProTxPubKeyConflicts(const CTransaction& tx, const CKeyID& keyId)
719 : {
720 805 : if (mapProTxPubKeyIDs.count(keyId)) {
721 1 : const uint256& conflictHash = mapProTxPubKeyIDs.at(keyId);
722 1 : if (conflictHash != tx.GetHash() && mapTx.count(conflictHash)) {
723 1 : removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT);
724 : }
725 : }
726 403 : }
727 :
728 446 : void CTxMemPool::removeProTxPubKeyConflicts(const CTransaction& tx, const CBLSPublicKey& pubKey)
729 : {
730 892 : if (mapProTxBlsPubKeyHashes.count(pubKey.GetHash())) {
731 0 : const uint256& conflictHash = mapProTxBlsPubKeyHashes.at(pubKey.GetHash());
732 0 : if (conflictHash != tx.GetHash() && mapTx.count(conflictHash)) {
733 0 : removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT);
734 : }
735 : }
736 446 : }
737 :
738 214 : void CTxMemPool::removeProTxCollateralConflicts(const CTransaction &tx, const COutPoint &collateralOutpoint)
739 : {
740 428 : if (mapProTxCollaterals.count(collateralOutpoint)) {
741 0 : const uint256& conflictHash = mapProTxCollaterals.at(collateralOutpoint);
742 0 : if (conflictHash != tx.GetHash() && mapTx.count(conflictHash)) {
743 0 : removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT);
744 : }
745 : }
746 214 : }
747 :
748 18 : void CTxMemPool::removeProTxReferences(const uint256& proTxHash, MemPoolRemovalReason reason)
749 : {
750 : // Remove TXs that refer to a certain MN
751 26 : while (true) {
752 22 : auto it = mapProTxRefs.find(proTxHash);
753 22 : if (it == mapProTxRefs.end()) {
754 : break;
755 : }
756 4 : auto conflictIt = mapTx.find(it->second);
757 4 : if (conflictIt != mapTx.end()) {
758 4 : removeRecursive(conflictIt->GetTx(), reason);
759 : } else {
760 : // Should not happen as we track referencing TXs in addUnchecked/removeUnchecked.
761 : // But lets be on the safe side and not run into an endless loop...
762 0 : LogPrint(BCLog::MEMPOOL, "%s: ERROR: found invalid TX ref in mapProTxRefs, proTxHash=%s, txHash=%s\n", __func__, proTxHash.ToString(), it->second.ToString());
763 0 : mapProTxRefs.erase(it);
764 : }
765 4 : }
766 18 : }
767 :
768 252677 : void CTxMemPool::removeProTxSpentCollateralConflicts(const CTransaction &tx)
769 : {
770 505354 : auto mnList = deterministicMNManager->GetListAtChainTip();
771 649442 : for (const auto& in : tx.vin) {
772 396765 : auto collateralIt = mapProTxCollaterals.find(in.prevout);
773 396765 : if (collateralIt != mapProTxCollaterals.end()) {
774 : // These are not yet mined ProRegTxs
775 0 : removeProTxReferences(collateralIt->second, MemPoolRemovalReason::CONFLICT);
776 : }
777 793530 : auto dmn = mnList.GetMNByCollateral(in.prevout);
778 396765 : if (dmn) {
779 : // These are updates referring to a mined ProRegTx
780 14 : removeProTxReferences(dmn->proTxHash, MemPoolRemovalReason::CONFLICT);
781 : }
782 : }
783 252677 : }
784 :
785 252677 : void CTxMemPool::removeProTxConflicts(const CTransaction &tx)
786 : {
787 252677 : removeProTxSpentCollateralConflicts(tx);
788 :
789 254138 : if (!tx.IsSpecialTx()) return;
790 :
791 2669 : const uint256& txid = tx.GetHash();
792 2669 : switch(tx.nType) {
793 403 : case CTransaction::TxType::PROREG: {
794 403 : ProRegPL pl;
795 403 : if (!GetTxPayload(tx, pl)) {
796 0 : LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx.ToString());
797 0 : return;
798 : }
799 804 : if (mapProTxAddresses.count(pl.addr)) {
800 2 : const uint256& conflictHash = mapProTxAddresses.at(pl.addr);
801 2 : if (conflictHash != txid && mapTx.count(conflictHash)) {
802 2 : removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT);
803 : }
804 : }
805 403 : removeProTxPubKeyConflicts(tx, pl.keyIDOwner);
806 403 : removeProTxPubKeyConflicts(tx, pl.pubKeyOperator);
807 6665 : if (!pl.collateralOutpoint.hash.IsNull()) {
808 214 : removeProTxCollateralConflicts(tx, pl.collateralOutpoint);
809 : }
810 403 : break;
811 : }
812 :
813 29 : case CTransaction::TxType::PROUPSERV: {
814 29 : ProUpServPL pl;
815 29 : if (!GetTxPayload(tx, pl)) {
816 0 : LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx.ToString());
817 0 : return;
818 : }
819 58 : if (mapProTxAddresses.count(pl.addr)) {
820 0 : const uint256& conflictHash = mapProTxAddresses.at(pl.addr);
821 0 : if (conflictHash != txid && mapTx.count(conflictHash)) {
822 0 : removeRecursive(mapTx.find(conflictHash)->GetTx(), MemPoolRemovalReason::CONFLICT);
823 : }
824 : }
825 29 : break;
826 : }
827 :
828 43 : case CTransaction::TxType::PROUPREG: {
829 43 : ProUpRegPL pl;
830 43 : if (!GetTxPayload(tx, pl)) {
831 0 : LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx.ToString());
832 0 : return;
833 : }
834 43 : removeProTxPubKeyConflicts(tx, pl.pubKeyOperator);
835 43 : break;
836 : }
837 :
838 : }
839 : }
840 :
841 : /**
842 : * Called when a block is connected. Removes from mempool and updates the miner fee estimator.
843 : */
844 41715 : void CTxMemPool::removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight)
845 : {
846 41715 : LOCK(cs);
847 83430 : std::vector<const CTxMemPoolEntry*> entries;
848 294392 : for (const auto& tx : vtx) {
849 252677 : uint256 hash = tx->GetHash();
850 252677 : indexed_transaction_set::iterator i = mapTx.find(hash);
851 252677 : if (i != mapTx.end())
852 161447 : entries.push_back(&*i);
853 : }
854 : // Before the txs in the new block have been removed from the mempool, update policy estimates
855 41715 : minerPolicyEstimator->processBlock(nBlockHeight, entries);
856 294392 : for (const auto& tx : vtx) {
857 252677 : txiter it = mapTx.find(tx->GetHash());
858 252677 : if (it != mapTx.end()) {
859 322894 : setEntries stage;
860 161447 : stage.insert(it);
861 161447 : RemoveStaged(stage, true, MemPoolRemovalReason::BLOCK);
862 : }
863 252677 : removeConflicts(*tx);
864 252677 : removeProTxConflicts(*tx);
865 252677 : ClearPrioritisation(tx->GetHash());
866 : }
867 41715 : lastRollingFeeUpdate = GetTime();
868 41715 : blockSinceLastRollingFeeBump = true;
869 41715 : }
870 :
871 :
872 970 : void CTxMemPool::_clear()
873 : {
874 970 : mapLinks.clear();
875 970 : mapTx.clear();
876 970 : mapNextTx.clear();
877 970 : mapProTxAddresses.clear();
878 970 : mapProTxPubKeyIDs.clear();
879 970 : totalTxSize = 0;
880 970 : cachedInnerUsage = 0;
881 970 : lastRollingFeeUpdate = GetTime();
882 970 : blockSinceLastRollingFeeBump = false;
883 970 : rollingMinimumFeeRate = 0;
884 970 : ++nTransactionsUpdated;
885 970 : }
886 :
887 486 : void CTxMemPool::clear()
888 : {
889 486 : LOCK(cs);
890 486 : _clear();
891 486 : }
892 :
893 50508 : void CTxMemPool::check(const CCoinsViewCache* pcoins) const
894 : {
895 50508 : if (nCheckFrequency == 0)
896 2718 : return;
897 :
898 47790 : if (GetRand(std::numeric_limits<uint32_t>::max()) >= nCheckFrequency)
899 : return;
900 :
901 47790 : LogPrint(BCLog::MEMPOOL, "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
902 :
903 47790 : uint64_t checkTotal = 0;
904 47790 : uint64_t innerUsage = 0;
905 :
906 47790 : CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins));
907 :
908 95580 : LOCK(cs);
909 95580 : std::list<const CTxMemPoolEntry*> waitingOnDependants;
910 2616900 : for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
911 2521320 : unsigned int i = 0;
912 2521320 : checkTotal += it->GetTxSize();
913 2521320 : innerUsage += it->DynamicMemoryUsage();
914 2521320 : const CTransaction& tx = it->GetTx();
915 2521320 : txlinksMap::const_iterator linksiter = mapLinks.find(it);
916 2521320 : assert(linksiter != mapLinks.end());
917 2521320 : const TxLinks &links = linksiter->second;
918 2521320 : innerUsage += memusage::DynamicUsage(links.parents) + memusage::DynamicUsage(links.children);
919 2521320 : bool fDependsWait = false;
920 5042650 : setEntries setParentCheck;
921 2521320 : int64_t parentSizes = 0;
922 2521320 : unsigned int parentSigOpCount = 0;
923 5969690 : for (const CTxIn& txin : tx.vin) {
924 : // Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
925 3448360 : indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
926 3448360 : if (it2 != mapTx.end()) {
927 22178 : const CTransaction& tx2 = it2->GetTx();
928 22178 : assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
929 22178 : fDependsWait = true;
930 22178 : if (setParentCheck.insert(it2).second) {
931 3448360 : parentSizes += it2->GetTxSize();
932 3448360 : parentSigOpCount += it2->GetSigOpCount();
933 : }
934 : } else {
935 3426180 : assert(pcoins->HaveCoin(txin.prevout));
936 : }
937 : // Check whether its inputs are marked in mapNextTx.
938 3448360 : auto it3 = mapNextTx.find(txin.prevout);
939 3448360 : assert(it3 != mapNextTx.end());
940 3448360 : assert(it3->first == &txin.prevout);
941 3448360 : assert(*it3->second == tx);
942 3448360 : i++;
943 : }
944 : // sapling txes
945 2521320 : if (tx.IsShieldedTx()) {
946 501533 : for (const SpendDescription& sd : tx.sapData->vShieldedSpend) {
947 244 : SaplingMerkleTree tree;
948 122 : assert(pcoins->GetSaplingAnchorAt(sd.anchor, tree));
949 122 : assert(!pcoins->GetNullifier(sd.nullifier));
950 : }
951 : }
952 2521320 : assert(setParentCheck == GetMemPoolParents(it));
953 : // Verify ancestor state is correct.
954 5042650 : setEntries setAncestors;
955 2521320 : uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
956 5042650 : std::string dummy;
957 2521320 : CalculateMemPoolAncestors(*it, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy);
958 2521320 : uint64_t nCountCheck = setAncestors.size() + 1;
959 2521320 : uint64_t nSizeCheck = it->GetTxSize();
960 2521320 : CAmount nFeesCheck = it->GetModifiedFee();
961 2521320 : unsigned int nSigOpCheck = it->GetSigOpCount();
962 :
963 2573910 : for (const txiter& ancestorIt : setAncestors) {
964 52584 : nSizeCheck += ancestorIt->GetTxSize();
965 52584 : nFeesCheck += ancestorIt->GetModifiedFee();
966 52584 : nSigOpCheck += ancestorIt->GetSigOpCount();
967 : }
968 :
969 2521320 : assert(it->GetCountWithAncestors() == nCountCheck);
970 2521320 : assert(it->GetSizeWithAncestors() == nSizeCheck);
971 2521320 : assert(it->GetSigOpCountWithAncestors() == nSigOpCheck);
972 2521320 : assert(it->GetModFeesWithAncestors() == nFeesCheck);
973 :
974 : // Check children against mapNextTx
975 5042650 : CTxMemPool::setEntries setChildrenCheck;
976 2521320 : auto iter = mapNextTx.lower_bound(COutPoint(it->GetTx().GetHash(), 0));
977 2521320 : int64_t childSizes = 0;
978 2543500 : for (; iter != mapNextTx.end() && iter->first->hash == tx.GetHash(); ++iter) {
979 22178 : txiter childit = mapTx.find(iter->second->GetHash());
980 22178 : assert(childit != mapTx.end()); // mapNextTx points to in-mempool transactions
981 22178 : if (setChildrenCheck.insert(childit).second) {
982 22178 : childSizes += childit->GetTxSize();
983 : }
984 : }
985 2521320 : assert(setChildrenCheck == GetMemPoolChildren(it));
986 : // Also check to make sure size is greater than sum with immediate children.
987 : // just a sanity check, not definitive that this calc is correct...
988 2521320 : assert(it->GetSizeWithDescendants() >= (uint64_t)(childSizes + it->GetTxSize()));
989 :
990 :
991 2521320 : if (fDependsWait)
992 18050 : waitingOnDependants.push_back(&(*it));
993 : else {
994 5006550 : CValidationState state;
995 2503280 : PrecomputedTransactionData precomTxData(tx);
996 2503280 : assert(CheckInputs(tx, state, mempoolDuplicate, false, 0, false, precomTxData, nullptr));
997 2503280 : UpdateCoins(tx, mempoolDuplicate, 1000000);
998 : }
999 : }
1000 :
1001 47790 : unsigned int stepsSinceLastRemove = 0;
1002 77514 : while (!waitingOnDependants.empty()) {
1003 29724 : const CTxMemPoolEntry* entry = waitingOnDependants.front();
1004 29724 : waitingOnDependants.pop_front();
1005 59448 : CValidationState state;
1006 29724 : if (!mempoolDuplicate.HaveInputs(entry->GetTx())) {
1007 11674 : waitingOnDependants.push_back(entry);
1008 11674 : stepsSinceLastRemove++;
1009 11674 : assert(stepsSinceLastRemove < waitingOnDependants.size());
1010 : } else {
1011 18050 : PrecomputedTransactionData precomTxData(entry->GetTx());
1012 18050 : assert(CheckInputs(entry->GetTx(), state, mempoolDuplicate, false, 0, false, precomTxData, nullptr));
1013 18050 : UpdateCoins(entry->GetTx(), mempoolDuplicate, 1000000);
1014 18050 : stepsSinceLastRemove = 0;
1015 : }
1016 : }
1017 3496150 : for (auto it = mapNextTx.cbegin(); it != mapNextTx.cend(); it++) {
1018 3448360 : const uint256& hash = it->second->GetHash();
1019 3448360 : indexed_transaction_set::const_iterator it2 = mapTx.find(hash);
1020 6896720 : const CTransactionRef& tx = it2->GetSharedTx();
1021 3448360 : assert(it2 != mapTx.end());
1022 3448360 : assert(tx == it->second);
1023 : }
1024 :
1025 : // Consistency check for sapling nullifiers
1026 47790 : checkNullifiers();
1027 :
1028 47790 : assert(totalTxSize == checkTotal);
1029 47790 : assert(innerUsage == cachedInnerUsage);
1030 : }
1031 :
1032 47790 : void CTxMemPool::checkNullifiers() const
1033 : {
1034 47912 : for (const auto& it : mapSaplingNullifiers) {
1035 122 : const uint256& hash = it.second->GetHash();
1036 122 : const auto& findTx = mapTx.find(hash);
1037 122 : assert(findTx != mapTx.end());
1038 244 : const CTransactionRef& tx = findTx->GetSharedTx();
1039 122 : assert(*tx == *it.second);
1040 : }
1041 47790 : }
1042 :
1043 118975 : bool CTxMemPool::CompareDepthAndScore(const uint256& hasha, const uint256& hashb)
1044 : {
1045 237950 : LOCK(cs);
1046 118975 : indexed_transaction_set::const_iterator i = mapTx.find(hasha);
1047 118975 : if (i == mapTx.end()) return false;
1048 98150 : indexed_transaction_set::const_iterator j = mapTx.find(hashb);
1049 98150 : if (j == mapTx.end()) return true;
1050 95548 : uint64_t counta = i->GetCountWithAncestors();
1051 95548 : uint64_t countb = j->GetCountWithAncestors();
1052 95548 : if (counta == countb) {
1053 95520 : return CompareTxMemPoolEntryByScore()(*i, *j);
1054 : }
1055 28 : return counta < countb;
1056 : }
1057 :
1058 : namespace {
1059 : class DepthAndScoreComparator
1060 : {
1061 : public:
1062 18737800 : bool operator()(const CTxMemPool::indexed_transaction_set::const_iterator& a, const CTxMemPool::indexed_transaction_set::const_iterator& b) const
1063 : {
1064 18737800 : uint64_t counta = a->GetCountWithAncestors();
1065 18737800 : uint64_t countb = b->GetCountWithAncestors();
1066 18737800 : if (counta == countb) {
1067 18737500 : return CompareTxMemPoolEntryByScore()(*a, *b);
1068 : }
1069 248 : return counta < countb;
1070 : }
1071 : };
1072 : }
1073 :
1074 10952 : std::vector<CTxMemPool::indexed_transaction_set::const_iterator> CTxMemPool::GetSortedDepthAndScore() const
1075 : {
1076 10952 : std::vector<indexed_transaction_set::const_iterator> iters;
1077 10952 : AssertLockHeld(cs);
1078 :
1079 10952 : iters.reserve(mapTx.size());
1080 :
1081 3826490 : for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) {
1082 1902290 : iters.push_back(mi);
1083 : }
1084 10952 : std::sort(iters.begin(), iters.end(), DepthAndScoreComparator());
1085 10952 : return iters;
1086 : }
1087 :
1088 10605 : void CTxMemPool::queryHashes(std::vector<uint256>& vtxid)
1089 : {
1090 10605 : LOCK(cs);
1091 21210 : auto iters = GetSortedDepthAndScore();
1092 :
1093 10605 : vtxid.clear();
1094 10605 : vtxid.reserve(mapTx.size());
1095 :
1096 1912050 : for (auto it : iters) {
1097 1901450 : vtxid.emplace_back(it->GetTx().GetHash());
1098 : }
1099 10605 : }
1100 :
1101 23313 : static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it) {
1102 23313 : return TxMempoolInfo{it->GetSharedTx(), it->GetTime(), CFeeRate(it->GetFee(), it->GetTxSize()), it->GetModifiedFee() - it->GetFee()};
1103 : }
1104 :
1105 347 : std::vector<TxMempoolInfo> CTxMemPool::infoAll() const
1106 : {
1107 347 : LOCK(cs);
1108 694 : auto iters = GetSortedDepthAndScore();
1109 :
1110 347 : std::vector<TxMempoolInfo> ret;
1111 347 : ret.reserve(mapTx.size());
1112 1194 : for (auto it : iters) {
1113 1694 : ret.emplace_back(GetInfo(it));
1114 : }
1115 :
1116 694 : return ret;
1117 : }
1118 :
1119 0 : void CTxMemPool::getTransactions(std::set<uint256>& setTxid)
1120 : {
1121 0 : setTxid.clear();
1122 :
1123 0 : LOCK(cs);
1124 0 : for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi)
1125 0 : setTxid.insert(mi->GetTx().GetHash());
1126 0 : }
1127 :
1128 1162663 : std::shared_ptr<const CTransaction> CTxMemPool::get(const uint256& hash) const
1129 : {
1130 2325326 : LOCK(cs);
1131 1162663 : indexed_transaction_set::const_iterator i = mapTx.find(hash);
1132 1162663 : if (i == mapTx.end())
1133 1114920 : return nullptr;
1134 1210406 : return i->GetSharedTx();
1135 : }
1136 :
1137 26553 : TxMempoolInfo CTxMemPool::info(const uint256& hash) const
1138 : {
1139 53106 : LOCK(cs);
1140 26553 : indexed_transaction_set::const_iterator i = mapTx.find(hash);
1141 26553 : if (i == mapTx.end())
1142 26553 : return TxMempoolInfo();
1143 22466 : return GetInfo(i);
1144 : }
1145 :
1146 159063 : bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const
1147 : {
1148 161248 : if (!tx.IsSpecialTx()) return false;
1149 :
1150 159428 : LOCK(cs);
1151 :
1152 365 : switch(tx.nType) {
1153 330 : case CTransaction::TxType::PROREG: {
1154 660 : ProRegPL pl;
1155 330 : if (!GetTxPayload(tx, pl)) {
1156 0 : LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx.ToString());
1157 0 : return true; // i.e. can't decode payload == conflict
1158 : }
1159 661 : if (mapProTxAddresses.count(pl.addr) || mapProTxPubKeyIDs.count(pl.keyIDOwner) ||
1160 656 : mapProTxBlsPubKeyHashes.count(pl.pubKeyOperator.GetHash())) {
1161 3 : return true;
1162 : }
1163 4932 : if (!pl.collateralOutpoint.hash.IsNull()) {
1164 189 : if (mapProTxCollaterals.count(pl.collateralOutpoint)) {
1165 : // there is another ProRegTx that refers to the same collateral
1166 0 : return true;
1167 : }
1168 378 : if (mapNextTx.count(pl.collateralOutpoint)) {
1169 : // there is another tx that spends the collateral
1170 0 : return true;
1171 : }
1172 : }
1173 : return false;
1174 : }
1175 :
1176 8 : case CTransaction::TxType::PROUPSERV: {
1177 16 : ProUpServPL pl;
1178 8 : if (!GetTxPayload(tx, pl)) {
1179 0 : LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx.ToString());
1180 0 : return true; // i.e. can't decode payload == conflict
1181 : }
1182 8 : auto it = mapProTxAddresses.find(pl.addr);
1183 8 : return it != mapProTxAddresses.end() && it->second != pl.proTxHash;
1184 : }
1185 :
1186 19 : case CTransaction::TxType::PROUPREG: {
1187 38 : ProUpRegPL pl;
1188 19 : if (!GetTxPayload(tx, pl)) {
1189 0 : LogPrint(BCLog::MEMPOOL, "%s: ERROR: Invalid transaction payload, tx: %s\n", __func__, tx.ToString());
1190 0 : return true; // i.e. can't decode payload == conflict
1191 : }
1192 19 : auto it = mapProTxBlsPubKeyHashes.find(pl.pubKeyOperator.GetHash());
1193 19 : return it != mapProTxBlsPubKeyHashes.end() && it->second != pl.proTxHash;
1194 : }
1195 :
1196 : }
1197 : return false;
1198 : }
1199 :
1200 198 : CFeeRate CTxMemPool::estimateFee(int nBlocks) const
1201 : {
1202 198 : LOCK(cs);
1203 396 : return minerPolicyEstimator->estimateFee(nBlocks);
1204 : }
1205 :
1206 978 : CFeeRate CTxMemPool::estimateSmartFee(int nBlocks, int *answerFoundAtBlocks) const
1207 : {
1208 978 : LOCK(cs);
1209 1956 : return minerPolicyEstimator->estimateSmartFee(nBlocks, answerFoundAtBlocks, *this);
1210 : }
1211 :
1212 356 : bool CTxMemPool::WriteFeeEstimates(CAutoFile& fileout) const
1213 : {
1214 356 : try {
1215 356 : LOCK(cs);
1216 356 : fileout << 4029900; // version required to read: 4.2.99
1217 356 : fileout << CLIENT_VERSION; // version that wrote the file
1218 356 : minerPolicyEstimator->Write(fileout);
1219 0 : } catch (const std::exception&) {
1220 0 : LogPrintf("CTxMemPool::WriteFeeEstimates() : unable to write policy estimator data (non-fatal)\n");
1221 0 : return false;
1222 : }
1223 356 : return true;
1224 : }
1225 :
1226 84 : bool CTxMemPool::ReadFeeEstimates(CAutoFile& filein)
1227 : {
1228 84 : try {
1229 84 : int nVersionRequired, nVersionThatWrote;
1230 84 : filein >> nVersionRequired >> nVersionThatWrote;
1231 84 : if (nVersionRequired > CLIENT_VERSION)
1232 0 : return error("CTxMemPool::ReadFeeEstimates() : up-version (%d) fee estimate file\n", nVersionRequired);
1233 :
1234 84 : LOCK(cs);
1235 84 : minerPolicyEstimator->Read(filein, nVersionThatWrote);
1236 0 : } catch (const std::exception&) {
1237 0 : LogPrintf("CTxMemPool::ReadFeeEstimates() : unable to read policy estimator data (non-fatal)\n");
1238 0 : return false;
1239 : }
1240 84 : return true;
1241 : }
1242 :
1243 2 : void CTxMemPool::PrioritiseTransaction(const uint256& hash, const CAmount& nFeeDelta)
1244 : {
1245 2 : {
1246 2 : LOCK(cs);
1247 2 : CAmount &delta = mapDeltas[hash];
1248 2 : delta += nFeeDelta;
1249 2 : txiter it = mapTx.find(hash);
1250 2 : if (it != mapTx.end()) {
1251 1 : mapTx.modify(it, update_fee_delta(delta));
1252 : // Now update all ancestors' modified fees with descendants
1253 2 : setEntries setAncestors;
1254 1 : uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
1255 2 : std::string dummy;
1256 1 : CalculateMemPoolAncestors(*it, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
1257 25 : for (const txiter& ancestorIt : setAncestors) {
1258 24 : mapTx.modify(ancestorIt, update_descendant_state(0, nFeeDelta, 0));
1259 : }
1260 : }
1261 : }
1262 4 : LogPrintf("PrioritiseTransaction: %s feerate += %s\n", hash.ToString(), FormatMoney(nFeeDelta));
1263 2 : }
1264 :
1265 147490 : void CTxMemPool::ApplyDelta(const uint256& hash, CAmount& nFeeDelta) const
1266 : {
1267 147491 : LOCK(cs);
1268 147490 : std::map<uint256, CAmount>::const_iterator pos = mapDeltas.find(hash);
1269 147490 : if (pos == mapDeltas.end())
1270 294978 : return;
1271 1 : const CAmount &delta = pos->second;
1272 1 : nFeeDelta += delta;
1273 : }
1274 :
1275 252677 : void CTxMemPool::ClearPrioritisation(const uint256 hash)
1276 : {
1277 252677 : LOCK(cs);
1278 252677 : mapDeltas.erase(hash);
1279 252677 : }
1280 :
1281 278 : bool CTxMemPool::nullifierExists(const uint256& nullifier) const
1282 : {
1283 278 : LOCK(cs);
1284 556 : return mapSaplingNullifiers.count(nullifier);
1285 : }
1286 :
1287 119239 : bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const
1288 : {
1289 119239 : if (tx.HasZerocoinSpendInputs())
1290 : return true;
1291 343688 : for (unsigned int i = 0; i < tx.vin.size(); i++)
1292 224518 : if (exists(tx.vin[i].prevout.hash))
1293 : return false;
1294 : return true;
1295 : }
1296 :
1297 :
1298 261834 : CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView* baseIn, CTxMemPool& mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) {}
1299 :
1300 941842 : bool CCoinsViewMemPool::GetCoin(const COutPoint& outpoint, Coin& coin) const
1301 : {
1302 : // If an entry in the mempool exists, always return that one, as it's guaranteed to never
1303 : // conflict with the underlying cache, and it cannot have pruned entries (as it contains full)
1304 : // transactions. First checking the underlying cache risks returning a pruned entry instead.
1305 1883680 : CTransactionRef ptx = mempool.get(outpoint.hash);
1306 941842 : if (ptx) {
1307 30983 : if (outpoint.n < ptx->vout.size()) {
1308 30983 : coin = Coin(ptx->vout[outpoint.n], MEMPOOL_HEIGHT, false, false);
1309 30983 : return true;
1310 : } else {
1311 : return false;
1312 : }
1313 : }
1314 910859 : return (base->GetCoin(outpoint, coin) && !coin.IsSpent());
1315 : }
1316 :
1317 0 : bool CCoinsViewMemPool::HaveCoin(const COutPoint& outpoint) const
1318 : {
1319 0 : return mempool.exists(outpoint) || base->HaveCoin(outpoint);
1320 : }
1321 :
1322 138 : bool CCoinsViewMemPool::GetNullifier(const uint256& nullifier) const
1323 : {
1324 138 : return mempool.nullifierExists(nullifier) || base->GetNullifier(nullifier);
1325 : }
1326 :
1327 518532 : size_t CTxMemPool::DynamicMemoryUsage() const
1328 : {
1329 518532 : LOCK(cs);
1330 : // Estimate the overhead of mapTx to be 15 pointers + an allocation, as no exact formula for
1331 : // boost::multi_index_contained is implemented.
1332 518532 : return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 15 * sizeof(void*)) * mapTx.size() +
1333 518532 : memusage::DynamicUsage(mapNextTx) +
1334 518532 : memusage::DynamicUsage(mapDeltas) +
1335 518532 : memusage::DynamicUsage(mapLinks) +
1336 518532 : cachedInnerUsage +
1337 518532 : memusage::DynamicUsage(mapSaplingNullifiers);
1338 : }
1339 :
1340 293025 : void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason)
1341 : {
1342 293025 : AssertLockHeld(cs);
1343 293025 : UpdateForRemoveFromMempool(stage, updateDescendants);
1344 455854 : for (const txiter& it : stage) {
1345 162829 : removeUnchecked(it, reason);
1346 : }
1347 293025 : }
1348 :
1349 119359 : int CTxMemPool::Expire(int64_t time)
1350 : {
1351 119359 : LOCK(cs);
1352 119359 : indexed_transaction_set::index<entry_time>::type::iterator it = mapTx.get<entry_time>().begin();
1353 238718 : setEntries toremove;
1354 119359 : while (it != mapTx.get<entry_time>().end() && it->GetTime() < time) {
1355 0 : toremove.insert(mapTx.project<0>(it));
1356 0 : it++;
1357 : }
1358 238718 : setEntries stage;
1359 119359 : for (const txiter& removeit : toremove) {
1360 0 : CalculateDescendants(removeit, stage);
1361 : }
1362 119359 : RemoveStaged(stage, false, MemPoolRemovalReason::EXPIRY);
1363 238718 : return stage.size();
1364 : }
1365 :
1366 19876 : bool CTxMemPool::addUnchecked(const uint256&hash, const CTxMemPoolEntry &entry, bool validFeeEstimate)
1367 : {
1368 19876 : LOCK(cs);
1369 39752 : setEntries setAncestors;
1370 19876 : uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
1371 39752 : std::string dummy;
1372 19876 : CalculateMemPoolAncestors(entry, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy);
1373 39752 : return addUnchecked(hash, entry, setAncestors, validFeeEstimate);
1374 : }
1375 :
1376 38545 : void CTxMemPool::UpdateChild(txiter entry, txiter child, bool add)
1377 : {
1378 38545 : setEntries s;
1379 38545 : if (add && mapLinks[entry].children.insert(child).second) {
1380 38523 : cachedInnerUsage += memusage::IncrementalDynamicUsage(s);
1381 22 : } else if (!add && mapLinks[entry].children.erase(child)) {
1382 22 : cachedInnerUsage -= memusage::IncrementalDynamicUsage(s);
1383 : }
1384 38545 : }
1385 :
1386 73763 : void CTxMemPool::UpdateParent(txiter entry, txiter parent, bool add)
1387 : {
1388 73763 : setEntries s;
1389 73763 : if (add && mapLinks[entry].parents.insert(parent).second) {
1390 38523 : cachedInnerUsage += memusage::IncrementalDynamicUsage(s);
1391 35240 : } else if (!add && mapLinks[entry].parents.erase(parent)) {
1392 35240 : cachedInnerUsage -= memusage::IncrementalDynamicUsage(s);
1393 : }
1394 73763 : }
1395 :
1396 5841620 : const CTxMemPool::setEntries & CTxMemPool::GetMemPoolParents(txiter entry) const
1397 : {
1398 5841620 : assert (entry != mapTx.end());
1399 5841620 : txlinksMap::const_iterator it = mapLinks.find(entry);
1400 5841620 : assert(it != mapLinks.end());
1401 5841620 : return it->second.parents;
1402 : }
1403 :
1404 5762390 : const CTxMemPool::setEntries & CTxMemPool::GetMemPoolChildren(txiter entry) const
1405 : {
1406 5762390 : assert (entry != mapTx.end());
1407 5762390 : txlinksMap::const_iterator it = mapLinks.find(entry);
1408 5762390 : assert(it != mapLinks.end());
1409 5762390 : return it->second.children;
1410 : }
1411 :
1412 1373 : CFeeRate CTxMemPool::GetMinFee(size_t sizelimit) const
1413 : {
1414 2746 : LOCK(cs);
1415 1373 : if (!blockSinceLastRollingFeeBump || rollingMinimumFeeRate == 0)
1416 1368 : return CFeeRate(rollingMinimumFeeRate);
1417 :
1418 5 : int64_t time = GetTime();
1419 5 : if (time > lastRollingFeeUpdate + 10) {
1420 5 : double halflife = ROLLING_FEE_HALFLIFE;
1421 5 : if (DynamicMemoryUsage() < sizelimit / 4)
1422 : halflife /= 4;
1423 4 : else if (DynamicMemoryUsage() < sizelimit / 2)
1424 1 : halflife /= 2;
1425 :
1426 5 : rollingMinimumFeeRate = rollingMinimumFeeRate / pow(2.0, (time - lastRollingFeeUpdate) / halflife);
1427 5 : lastRollingFeeUpdate = time;
1428 :
1429 5 : if (rollingMinimumFeeRate < (double)minReasonableRelayFee.GetFeePerK() / 2) {
1430 1 : rollingMinimumFeeRate = 0;
1431 1 : return CFeeRate(0);
1432 : }
1433 : }
1434 5 : return std::max(CFeeRate(rollingMinimumFeeRate), minReasonableRelayFee);
1435 : }
1436 :
1437 6 : void CTxMemPool::trackPackageRemoved(const CFeeRate& rate)
1438 : {
1439 6 : AssertLockHeld(cs);
1440 6 : if (rate.GetFeePerK() > rollingMinimumFeeRate) {
1441 4 : rollingMinimumFeeRate = rate.GetFeePerK();
1442 4 : blockSinceLastRollingFeeBump = false;
1443 : }
1444 6 : }
1445 :
1446 266431 : void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<COutPoint>* pvNoSpendsRemaining)
1447 : {
1448 266431 : LOCK(cs);
1449 266431 : unsigned nTxnRemoved = 0;
1450 266431 : CFeeRate maxFeeRateRemoved(0);
1451 266437 : while (DynamicMemoryUsage() > sizelimit) {
1452 6 : indexed_transaction_set::index<descendant_score>::type::iterator it = mapTx.get<descendant_score>().begin();
1453 :
1454 : // We set the new mempool min fee to the feerate of the removed set, plus the
1455 : // "minimum reasonable fee rate" (ie some value under which we consider txn
1456 : // to have 0 fee). This way, we don't allow txn to enter mempool with feerate
1457 : // equal to txn which were removed with no block in between.
1458 6 : CFeeRate removed(it->GetModFeesWithDescendants(), it->GetSizeWithDescendants());
1459 6 : removed += minReasonableRelayFee;
1460 6 : trackPackageRemoved(removed);
1461 6 : maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
1462 :
1463 12 : setEntries stage;
1464 6 : CalculateDescendants(mapTx.project<0>(it), stage);
1465 6 : nTxnRemoved += stage.size();
1466 :
1467 12 : std::vector<CTransaction> txn;
1468 6 : if (pvNoSpendsRemaining) {
1469 0 : txn.reserve(stage.size());
1470 0 : for (txiter it: stage)
1471 0 : txn.push_back(it->GetTx());
1472 : }
1473 6 : RemoveStaged(stage, false, MemPoolRemovalReason::SIZELIMIT);
1474 6 : if (pvNoSpendsRemaining) {
1475 0 : for (const CTransaction& tx: txn) {
1476 0 : for (const CTxIn& txin: tx.vin) {
1477 0 : if (exists(txin.prevout.hash)) continue;
1478 0 : if (!mapNextTx.count(txin.prevout)) {
1479 0 : pvNoSpendsRemaining->push_back(txin.prevout);
1480 : }
1481 : }
1482 : }
1483 : }
1484 : }
1485 :
1486 266431 : if (maxFeeRateRemoved > CFeeRate(0))
1487 6 : LogPrint(BCLog::MEMPOOL, "Removed %u txn, rolling minimum fee bumped to %s\n", nTxnRemoved, maxFeeRateRemoved.ToString());
1488 266431 : }
1489 :
1490 511907 : bool CTxMemPool::TransactionWithinChainLimit(const uint256& txid, size_t chainLimit) const {
1491 511907 : LOCK(cs);
1492 511907 : auto it = mapTx.find(txid);
1493 512222 : return it == mapTx.end() || (it->GetCountWithAncestors() < chainLimit &&
1494 512373 : it->GetCountWithDescendants() < chainLimit);
1495 : }
1496 :
1497 756 : bool CTxMemPool::IsLoaded() const
1498 : {
1499 756 : LOCK(cs);
1500 756 : return m_is_loaded;
1501 : }
1502 :
1503 355 : void CTxMemPool::SetIsLoaded(bool loaded)
1504 : {
1505 355 : LOCK(cs);
1506 355 : m_is_loaded = loaded;
1507 355 : }
1508 :
|