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 191541 : CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee,
27 : int64_t _nTime, unsigned int _entryHeight,
28 191541 : bool _spendsCoinbaseOrCoinstake, unsigned int _sigOps) :
29 191541 : tx(MakeTransactionRef(_tx)), nFee(_nFee), nTime(_nTime), entryHeight(_entryHeight),
30 191541 : spendsCoinbaseOrCoinstake(_spendsCoinbaseOrCoinstake), sigOpCount(_sigOps)
31 : {
32 191541 : nTxSize = ::GetSerializeSize(*_tx, PROTOCOL_VERSION);
33 191541 : nUsageSize = _tx->DynamicMemoryUsage();
34 191541 : hasZerocoins = _tx->ContainsZerocoins();
35 191541 : m_isShielded = _tx->IsShieldedTx();
36 :
37 191541 : nCountWithDescendants = 1;
38 191541 : nSizeWithDescendants = nTxSize;
39 191541 : nModFeesWithDescendants = nFee;
40 :
41 191541 : feeDelta = 0;
42 :
43 191541 : nCountWithAncestors = 1;
44 191541 : nSizeWithAncestors = nTxSize;
45 191541 : nModFeesWithAncestors = nFee;
46 191541 : nSigOpCountWithAncestors = sigOpCount;
47 191541 : }
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 51693 : void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendants, const std::set<uint256> &setExclude)
60 : {
61 103386 : setEntries stageEntries, setAllDescendants;
62 51693 : stageEntries = GetMemPoolChildren(updateIt);
63 :
64 109020 : while (!stageEntries.empty()) {
65 57327 : const txiter cit = *stageEntries.begin();
66 57327 : setAllDescendants.insert(cit);
67 57327 : stageEntries.erase(cit);
68 57327 : const setEntries &setChildren = GetMemPoolChildren(cit);
69 77728 : for (const txiter& childEntry : setChildren) {
70 20401 : cacheMap::iterator cacheIt = cachedDescendants.find(childEntry);
71 20401 : 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 4894 : for (const txiter& cacheEntry : cacheIt->second) {
75 2576 : setAllDescendants.insert(cacheEntry);
76 : }
77 18084 : } else if (!setAllDescendants.count(childEntry)) {
78 : // Schedule for later processing
79 38483 : 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 51693 : int64_t modifySize = 0;
86 51693 : CAmount modifyFee = 0;
87 51693 : int64_t modifyCount = 0;
88 111596 : for (const txiter& cit : setAllDescendants) {
89 103357 : if (!setExclude.count(cit->GetTx().GetHash())) {
90 16449 : modifySize += cit->GetTxSize();
91 16449 : modifyFee += cit->GetModifiedFee();
92 16449 : modifyCount++;
93 16449 : cachedDescendants[updateIt].insert(cit);
94 : // Update ancestor state for each descendant
95 16449 : mapTx.modify(cit, update_ancestor_state(updateIt->GetTxSize(), updateIt->GetModifiedFee(), 1, updateIt->GetSigOpCount()));
96 : }
97 : }
98 51693 : mapTx.modify(updateIt, update_descendant_state(modifySize, modifyFee, modifyCount));
99 51693 : }
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 66 : void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashesToUpdate)
107 : {
108 66 : 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 132 : 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 132 : 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 51759 : for (const uint256 &hash : reverse_iterate(vHashesToUpdate)) {
124 : // we cache the in-mempool children to avoid duplicate updates
125 103386 : setEntries setChildren;
126 : // calculate children from mapNextTx
127 51693 : txiter it = mapTx.find(hash);
128 51693 : if (it == mapTx.end()) {
129 0 : continue;
130 : }
131 51693 : 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 90938 : for (; iter != mapNextTx.end() && iter->first->hash == hash; ++iter) {
135 39245 : const uint256 &childHash = iter->second->GetHash();
136 39245 : txiter childIter = mapTx.find(childHash);
137 39245 : 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 69884 : if (setChildren.insert(childIter).second && !setAlreadyIncluded.count(childHash)) {
141 8606 : UpdateChild(it, childIter, true);
142 8606 : UpdateParent(childIter, it, true);
143 : }
144 : }
145 51693 : UpdateForDescendants(it, mapMemPoolDescendantsToUpdate, setAlreadyIncluded);
146 : }
147 66 : }
148 :
149 3599044 : 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 7198088 : setEntries parentHashes;
152 7198088 : const auto &tx = entry.GetSharedTx();
153 :
154 3599044 : 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 7883439 : for (unsigned int i = 0; i < tx->vin.size(); i++) {
159 4614218 : txiter piter = mapTx.find(tx->vin[i].prevout.hash);
160 4614218 : if (piter != mapTx.end()) {
161 69090 : parentHashes.insert(piter);
162 69090 : 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 329829 : txiter it = mapTx.iterator_to(entry);
172 329829 : parentHashes = GetMemPoolParents(it);
173 : }
174 :
175 3599044 : size_t totalSizeWithAncestors = entry.GetTxSize();
176 :
177 6270080 : while (!parentHashes.empty()) {
178 2671043 : txiter stageit = *parentHashes.begin();
179 :
180 2671043 : setAncestors.insert(stageit);
181 2671043 : parentHashes.erase(stageit);
182 2671043 : totalSizeWithAncestors += stageit->GetTxSize();
183 :
184 2671043 : 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 5 : return false;
187 2671043 : } else if (stageit->GetCountWithDescendants() + 1 > limitDescendantCount) {
188 1 : errString = strprintf("too many descendants for tx %s [limit: %u]", stageit->GetTx().GetHash().ToString(), limitDescendantCount);
189 1 : return false;
190 2671042 : } else if (totalSizeWithAncestors > limitAncestorSize) {
191 0 : errString = strprintf("exceeds ancestor size limit [limit: %u]", limitAncestorSize);
192 0 : return false;
193 : }
194 :
195 2671042 : const setEntries & setMemPoolParents = GetMemPoolParents(stageit);
196 5253566 : for (const txiter& phash : setMemPoolParents) {
197 : // If this is a new ancestor, add it.
198 2582540 : if (setAncestors.count(phash) == 0) {
199 2582516 : parentHashes.insert(phash);
200 : }
201 2582528 : if (parentHashes.size() + setAncestors.size() + 1 > limitAncestorCount) {
202 4 : errString = strprintf("too many unconfirmed ancestors [limit: %u]", limitAncestorCount);
203 4 : return false;
204 : }
205 : }
206 : }
207 :
208 : return true;
209 : }
210 :
211 377908 : void CTxMemPool::UpdateAncestorsOf(bool add, txiter it, setEntries &setAncestors)
212 : {
213 377908 : setEntries parentIters = GetMemPoolParents(it);
214 : // add or remove this tx as a child of each parent
215 411930 : for (const txiter& piter : parentIters) {
216 34022 : UpdateChild(piter, it, add);
217 : }
218 377908 : const int64_t updateCount = (add ? 1 : -1);
219 377908 : const int64_t updateSize = updateCount * it->GetTxSize();
220 377908 : const CAmount updateFee = updateCount * it->GetModifiedFee();
221 2949800 : for (const txiter& ancestorIt : setAncestors) {
222 2571898 : mapTx.modify(ancestorIt, update_descendant_state(updateSize, updateFee, updateCount));
223 : }
224 377908 : }
225 :
226 191011 : void CTxMemPool::UpdateEntryForAncestors(txiter it, const setEntries &setAncestors)
227 : {
228 191011 : int64_t updateCount = setAncestors.size();
229 191011 : int64_t updateSize = 0;
230 191011 : CAmount updateFee = 0;
231 191011 : int updateSigOps = 0;
232 2762879 : for (const txiter& ancestorIt : setAncestors) {
233 2571868 : updateSize += ancestorIt->GetTxSize();
234 2571868 : updateFee += ancestorIt->GetModifiedFee();
235 2571868 : updateSigOps += ancestorIt->GetSigOpCount();
236 : }
237 191011 : mapTx.modify(it, update_ancestor_state(updateSize, updateFee, updateCount, updateSigOps));
238 191011 : }
239 :
240 186897 : void CTxMemPool::UpdateChildrenForRemoval(txiter it)
241 : {
242 186897 : const setEntries &setMemPoolChildren = GetMemPoolChildren(it);
243 226222 : for (const txiter& updateIt : setMemPoolChildren) {
244 39325 : UpdateParent(updateIt, it, false);
245 : }
246 186897 : }
247 :
248 321986 : 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 321986 : const uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
253 321986 : 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 370930 : for (const txiter& removeIt : entriesToRemove) {
261 370930 : setEntries setDescendants;
262 185465 : CalculateDescendants(removeIt, setDescendants);
263 185465 : setDescendants.erase(removeIt); // don't update state for self
264 185465 : int64_t modifySize = -((int64_t)removeIt->GetTxSize());
265 185465 : CAmount modifyFee = -removeIt->GetModifiedFee();
266 185465 : int modifySigOps = -removeIt->GetSigOpCount();
267 249144 : for (const txiter& dit : setDescendants) {
268 63679 : mapTx.modify(dit, update_ancestor_state(modifySize, modifyFee, -1, modifySigOps));
269 : }
270 : }
271 : }
272 508883 : for (const txiter& removeIt : entriesToRemove) {
273 373794 : setEntries setAncestors;
274 186897 : const CTxMemPoolEntry &entry = *removeIt;
275 373794 : 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 186897 : 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 186897 : 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 508883 : for (const txiter& removeIt : entriesToRemove) {
302 186897 : UpdateChildrenForRemoval(removeIt);
303 : }
304 321986 : }
305 :
306 2623612 : void CTxMemPoolEntry::UpdateDescendantState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount)
307 : {
308 2623612 : nSizeWithDescendants += modifySize;
309 2623612 : assert(int64_t(nSizeWithDescendants) > 0);
310 2623612 : nModFeesWithDescendants += modifyFee;
311 2623612 : nCountWithDescendants += modifyCount;
312 2623612 : assert(int64_t(nCountWithDescendants) > 0);
313 2623612 : }
314 :
315 271139 : void CTxMemPoolEntry::UpdateAncestorState(int64_t modifySize, CAmount modifyFee, int64_t modifyCount, int modifySigOps)
316 : {
317 271139 : nSizeWithAncestors += modifySize;
318 271139 : assert(int64_t(nSizeWithAncestors) > 0);
319 271139 : nModFeesWithAncestors += modifyFee;
320 271139 : nCountWithAncestors += modifyCount;
321 271139 : assert(int64_t(nCountWithAncestors) > 0);
322 271139 : nSigOpCountWithAncestors += modifySigOps;
323 271139 : assert(int(nSigOpCountWithAncestors) >= 0);
324 271139 : }
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 42275 : void CTxMemPool::AddTransactionsUpdated(unsigned int n)
358 : {
359 42275 : LOCK(cs);
360 42275 : nTransactionsUpdated += n;
361 42275 : }
362 :
363 191011 : void CTxMemPool::addUncheckedSpecialTx(const CTransaction& tx)
364 : {
365 193191 : 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 367 : const uint256& txid = tx.GetHash();
371 367 : switch(tx.nType) {
372 327 : case CTransaction::TxType::PROREG: {
373 327 : ProRegPL pl;
374 327 : bool ok = GetTxPayload(tx, pl);
375 327 : assert(ok);
376 4808 : if (!pl.collateralOutpoint.hash.IsNull()) {
377 193 : mapProTxRefs.emplace(txid, pl.collateralOutpoint.hash);
378 193 : mapProTxCollaterals.emplace(pl.collateralOutpoint, txid);
379 : }
380 327 : mapProTxAddresses.emplace(pl.addr, txid);
381 327 : mapProTxPubKeyIDs.emplace(pl.keyIDOwner, txid);
382 327 : mapProTxBlsPubKeyHashes.emplace(pl.pubKeyOperator.GetHash(), txid);
383 327 : break;
384 : }
385 :
386 12 : case CTransaction::TxType::PROUPSERV: {
387 12 : ProUpServPL pl;
388 12 : bool ok = GetTxPayload(tx, pl);
389 12 : assert(ok);
390 12 : mapProTxRefs.emplace(pl.proTxHash, txid);
391 12 : mapProTxAddresses.emplace(pl.addr, txid);
392 12 : break;
393 : }
394 :
395 20 : case CTransaction::TxType::PROUPREG: {
396 20 : ProUpRegPL pl;
397 20 : bool ok = GetTxPayload(tx, pl);
398 20 : assert(ok);
399 20 : mapProTxRefs.emplace(pl.proTxHash, txid);
400 20 : mapProTxBlsPubKeyHashes.emplace(pl.pubKeyOperator.GetHash(), txid);
401 20 : 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 191011 : 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 191011 : LOCK(cs);
420 191011 : indexed_transaction_set::iterator newit = mapTx.insert(entry).first;
421 191011 : 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 191011 : std::map<uint256, CAmount>::const_iterator pos = mapDeltas.find(hash);
427 191011 : 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 191011 : cachedInnerUsage += entry.DynamicMemoryUsage();
438 :
439 191011 : const CTransaction& tx = newit->GetTx();
440 382022 : std::set<uint256> setParentTransactions;
441 191011 : if(!tx.HasZerocoinSpendInputs()) {
442 539084 : for (unsigned int i = 0; i < tx.vin.size(); i++) {
443 696146 : mapNextTx.insert(std::make_pair(&tx.vin[i].prevout, newit->GetSharedTx()));
444 348073 : 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 539064 : for (const uint256& phash : setParentTransactions) {
456 348053 : txiter pit = mapTx.find(phash);
457 348053 : if (pit != mapTx.end()) {
458 34001 : UpdateParent(newit, pit, true);
459 : }
460 : }
461 191011 : UpdateAncestorsOf(true, newit, setAncestors);
462 191011 : UpdateEntryForAncestors(newit, setAncestors);
463 :
464 : // Save spent nullifiers
465 191011 : if (tx.IsShieldedTx()) {
466 2313 : for (const SpendDescription& sd : tx.sapData->vShieldedSpend) {
467 135 : mapSaplingNullifiers[sd.nullifier] = newit->GetSharedTx();
468 : }
469 : }
470 :
471 191011 : nTransactionsUpdated++;
472 191011 : totalTxSize += entry.GetTxSize();
473 191011 : minerPolicyEstimator->processTransaction(entry, validFeeEstimate);
474 :
475 191011 : addUncheckedSpecialTx(tx);
476 :
477 382022 : return true;
478 : }
479 :
480 186897 : void CTxMemPool::removeUncheckedSpecialTx(const CTransaction& tx)
481 : {
482 188305 : if (!tx.IsSpecialTx()) return;
483 :
484 734 : auto eraseProTxRef = [&](const uint256& proTxHash, const uint256& txHash) {
485 367 : auto its = mapProTxRefs.equal_range(proTxHash);
486 367 : for (auto it = its.first; it != its.second;) {
487 236 : if (it->second == txHash) {
488 233 : it = mapProTxRefs.erase(it);
489 : } else {
490 606 : ++it;
491 : }
492 : }
493 734 : };
494 :
495 367 : const uint256& txid = tx.GetHash();
496 367 : switch(tx.nType) {
497 327 : case CTransaction::TxType::PROREG: {
498 327 : ProRegPL pl;
499 327 : bool ok = GetTxPayload(tx, pl);
500 327 : assert(ok);
501 4615 : if (!pl.collateralOutpoint.IsNull()) {
502 327 : eraseProTxRef(txid, pl.collateralOutpoint.hash);
503 : }
504 327 : mapProTxCollaterals.erase(pl.collateralOutpoint);
505 327 : mapProTxAddresses.erase(pl.addr);
506 327 : mapProTxPubKeyIDs.erase(pl.keyIDOwner);
507 327 : mapProTxBlsPubKeyHashes.erase(pl.pubKeyOperator.GetHash());
508 327 : break;
509 : }
510 :
511 12 : case CTransaction::TxType::PROUPSERV: {
512 12 : ProUpServPL pl;
513 12 : bool ok = GetTxPayload(tx, pl);
514 12 : assert(ok);
515 12 : eraseProTxRef(pl.proTxHash, txid);
516 12 : mapProTxAddresses.erase(pl.addr);
517 12 : break;
518 : }
519 :
520 20 : case CTransaction::TxType::PROUPREG: {
521 20 : ProUpRegPL pl;
522 20 : bool ok = GetTxPayload(tx, pl);
523 20 : assert(ok);
524 20 : eraseProTxRef(pl.proTxHash, txid);
525 20 : mapProTxBlsPubKeyHashes.erase(pl.pubKeyOperator.GetHash());
526 20 : 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 186897 : void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason)
541 : {
542 186897 : 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 2864 : GetMainSignals().TransactionRemovedFromMempool(it->GetSharedTx(), reason);
548 : }
549 :
550 186897 : AssertLockHeld(cs);
551 186897 : const CTransaction& tx = it->GetTx();
552 530857 : for (const CTxIn& txin : tx.vin)
553 343960 : mapNextTx.erase(txin.prevout);
554 : // Remove spent nullifiers
555 186897 : if (tx.IsShieldedTx()) {
556 1538 : for (const SpendDescription& sd : tx.sapData->vShieldedSpend) {
557 132 : mapSaplingNullifiers.erase(sd.nullifier);
558 : }
559 : }
560 :
561 186897 : removeUncheckedSpecialTx(tx);
562 :
563 186897 : totalTxSize -= it->GetTxSize();
564 186897 : cachedInnerUsage -= it->DynamicMemoryUsage();
565 186897 : cachedInnerUsage -= memusage::DynamicUsage(mapLinks[it].parents) + memusage::DynamicUsage(mapLinks[it].children);
566 186897 : mapLinks.erase(it);
567 186897 : mapTx.erase(it);
568 186897 : nTransactionsUpdated++;
569 186897 : minerPolicyEstimator->removeTx(tx.GetHash());
570 186897 : }
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 350235 : void CTxMemPool::CalculateDescendants(txiter entryit, setEntries &setDescendants)
579 : {
580 350235 : setEntries stage;
581 350235 : if (setDescendants.count(entryit) == 0) {
582 350235 : 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 3342978 : while (!stage.empty()) {
588 2992744 : txiter it = *stage.begin();
589 2992744 : setDescendants.insert(it);
590 2992744 : stage.erase(it);
591 :
592 2992744 : const setEntries &setChildren = GetMemPoolChildren(it);
593 5635256 : for (const txiter& childiter : setChildren) {
594 2642514 : if (!setDescendants.count(childiter)) {
595 5285022 : stage.insert(childiter);
596 : }
597 : }
598 : }
599 350235 : }
600 :
601 16948 : void CTxMemPool::removeRecursive(const CTransaction& origTx, MemPoolRemovalReason reason)
602 : {
603 : // Remove transaction from memory pool
604 16948 : {
605 16948 : LOCK(cs);
606 33896 : setEntries txToRemove;
607 16948 : txiter origit = mapTx.find(origTx.GetHash());
608 16948 : 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 53617 : for (unsigned int i = 0; i < origTx.vout.size(); i++) {
616 36684 : auto it = mapNextTx.find(COutPoint(origTx.GetHash(), i));
617 36684 : if (it == mapNextTx.end())
618 35288 : continue;
619 1396 : txiter nextit = mapTx.find(it->second->GetHash());
620 1396 : assert(nextit != mapTx.end());
621 1396 : txToRemove.insert(nextit);
622 : }
623 : }
624 33896 : setEntries setAllRemoves;
625 18359 : for (const txiter& it : txToRemove) {
626 1411 : CalculateDescendants(it, setAllRemoves);
627 : }
628 :
629 16948 : RemoveStaged(setAllRemoves, false, reason);
630 : }
631 16948 : }
632 :
633 66 : void CTxMemPool::removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags)
634 : {
635 66 : AssertLockHeld(cs_main);
636 : // Remove transactions spending a coinbase which are now immature and no-longer-final transactions
637 66 : LOCK(cs);
638 132 : setEntries txToRemove;
639 60459 : for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
640 120654 : const CTransactionRef& tx = it->GetSharedTx();
641 60327 : if (!CheckFinalTx(tx, flags)) {
642 60327 : txToRemove.insert(it);
643 60327 : } else if (it->GetSpendsCoinbaseOrCoinstake()) {
644 91 : for (const CTxIn& txin : tx->vin) {
645 53 : indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
646 53 : if (it2 != mapTx.end())
647 6 : continue;
648 47 : const Coin &coin = pcoins->AccessCoin(txin.prevout);
649 47 : if (nCheckFrequency != 0) assert(!coin.IsSpent());
650 47 : if (coin.IsSpent() || ((coin.IsCoinBase() || coin.IsCoinStake()) && ((signed long)nMemPoolHeight) - coin.nHeight < (signed long)Params().GetConsensus().nCoinbaseMaturity)) {
651 2 : txToRemove.insert(it);
652 2 : break;
653 : }
654 : }
655 : }
656 : }
657 132 : setEntries setAllRemoves;
658 68 : for (txiter it : txToRemove) {
659 2 : CalculateDescendants(it, setAllRemoves);
660 : }
661 66 : RemoveStaged(setAllRemoves, false, MemPoolRemovalReason::REORG);
662 66 : }
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 317171 : void CTxMemPool::removeConflicts(const CTransaction& tx)
689 : {
690 : // Remove transactions which depend on inputs of tx, recursively
691 317171 : std::list<CTransaction> result;
692 634342 : LOCK(cs);
693 842413 : for (const CTxIn& txin : tx.vin) {
694 525242 : auto it = mapNextTx.find(txin.prevout);
695 525242 : 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 321297 : if (tx.IsShieldedTx()) {
705 1606 : for (const SpendDescription& sd : tx.sapData->vShieldedSpend) {
706 147 : const auto& it = mapSaplingNullifiers.find(sd.nullifier);
707 147 : 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 317171 : }
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 317171 : void CTxMemPool::removeProTxSpentCollateralConflicts(const CTransaction &tx)
769 : {
770 634342 : auto mnList = deterministicMNManager->GetListAtChainTip();
771 842413 : for (const auto& in : tx.vin) {
772 525242 : auto collateralIt = mapProTxCollaterals.find(in.prevout);
773 525242 : if (collateralIt != mapProTxCollaterals.end()) {
774 : // These are not yet mined ProRegTxs
775 0 : removeProTxReferences(collateralIt->second, MemPoolRemovalReason::CONFLICT);
776 : }
777 1050486 : auto dmn = mnList.GetMNByCollateral(in.prevout);
778 525242 : if (dmn) {
779 : // These are updates referring to a mined ProRegTx
780 14 : removeProTxReferences(dmn->proTxHash, MemPoolRemovalReason::CONFLICT);
781 : }
782 : }
783 317171 : }
784 :
785 317171 : void CTxMemPool::removeProTxConflicts(const CTransaction &tx)
786 : {
787 317171 : removeProTxSpentCollateralConflicts(tx);
788 :
789 318632 : if (!tx.IsSpecialTx()) return;
790 :
791 2665 : const uint256& txid = tx.GetHash();
792 2665 : 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 42036 : void CTxMemPool::removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight)
845 : {
846 42036 : LOCK(cs);
847 84072 : std::vector<const CTxMemPoolEntry*> entries;
848 359207 : for (const auto& tx : vtx) {
849 317171 : uint256 hash = tx->GetHash();
850 317171 : indexed_transaction_set::iterator i = mapTx.find(hash);
851 317171 : if (i != mapTx.end())
852 185465 : entries.push_back(&*i);
853 : }
854 : // Before the txs in the new block have been removed from the mempool, update policy estimates
855 42036 : minerPolicyEstimator->processBlock(nBlockHeight, entries);
856 359207 : for (const auto& tx : vtx) {
857 317171 : txiter it = mapTx.find(tx->GetHash());
858 317171 : if (it != mapTx.end()) {
859 370930 : setEntries stage;
860 185465 : stage.insert(it);
861 185465 : RemoveStaged(stage, true, MemPoolRemovalReason::BLOCK);
862 : }
863 317171 : removeConflicts(*tx);
864 317171 : removeProTxConflicts(*tx);
865 317171 : ClearPrioritisation(tx->GetHash());
866 : }
867 42036 : lastRollingFeeUpdate = GetTime();
868 42036 : blockSinceLastRollingFeeBump = true;
869 42036 : }
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 50895 : void CTxMemPool::check(const CCoinsViewCache* pcoins) const
894 : {
895 50895 : if (nCheckFrequency == 0)
896 2719 : return;
897 :
898 48176 : if (GetRand(std::numeric_limits<uint32_t>::max()) >= nCheckFrequency)
899 : return;
900 :
901 48176 : LogPrint(BCLog::MEMPOOL, "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
902 :
903 48176 : uint64_t checkTotal = 0;
904 48176 : uint64_t innerUsage = 0;
905 :
906 48176 : CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins));
907 :
908 96352 : LOCK(cs);
909 96352 : std::list<const CTxMemPoolEntry*> waitingOnDependants;
910 3174040 : for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
911 3077690 : unsigned int i = 0;
912 3077690 : checkTotal += it->GetTxSize();
913 3077690 : innerUsage += it->DynamicMemoryUsage();
914 3077690 : const CTransaction& tx = it->GetTx();
915 3077690 : txlinksMap::const_iterator linksiter = mapLinks.find(it);
916 3077690 : assert(linksiter != mapLinks.end());
917 3077690 : const TxLinks &links = linksiter->second;
918 3077690 : innerUsage += memusage::DynamicUsage(links.parents) + memusage::DynamicUsage(links.children);
919 3077690 : bool fDependsWait = false;
920 6155380 : setEntries setParentCheck;
921 3077690 : int64_t parentSizes = 0;
922 3077690 : unsigned int parentSigOpCount = 0;
923 7343120 : for (const CTxIn& txin : tx.vin) {
924 : // Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
925 4265430 : indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
926 4265430 : if (it2 != mapTx.end()) {
927 35050 : const CTransaction& tx2 = it2->GetTx();
928 35050 : assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
929 35050 : fDependsWait = true;
930 35050 : if (setParentCheck.insert(it2).second) {
931 4265430 : parentSizes += it2->GetTxSize();
932 4265430 : parentSigOpCount += it2->GetSigOpCount();
933 : }
934 : } else {
935 4230380 : assert(pcoins->HaveCoin(txin.prevout));
936 : }
937 : // Check whether its inputs are marked in mapNextTx.
938 4265430 : auto it3 = mapNextTx.find(txin.prevout);
939 4265430 : assert(it3 != mapNextTx.end());
940 4265430 : assert(it3->first == &txin.prevout);
941 4265430 : assert(*it3->second == tx);
942 4265430 : i++;
943 : }
944 : // sapling txes
945 3077690 : if (tx.IsShieldedTx()) {
946 501532 : for (const SpendDescription& sd : tx.sapData->vShieldedSpend) {
947 242 : SaplingMerkleTree tree;
948 121 : assert(pcoins->GetSaplingAnchorAt(sd.anchor, tree));
949 121 : assert(!pcoins->GetNullifier(sd.nullifier));
950 : }
951 : }
952 3077690 : assert(setParentCheck == GetMemPoolParents(it));
953 : // Verify ancestor state is correct.
954 6155380 : setEntries setAncestors;
955 3077690 : uint64_t nNoLimit = std::numeric_limits<uint64_t>::max();
956 6155380 : std::string dummy;
957 3077690 : CalculateMemPoolAncestors(*it, setAncestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy);
958 3077690 : uint64_t nCountCheck = setAncestors.size() + 1;
959 3077690 : uint64_t nSizeCheck = it->GetTxSize();
960 3077690 : CAmount nFeesCheck = it->GetModifiedFee();
961 3077690 : unsigned int nSigOpCheck = it->GetSigOpCount();
962 :
963 3130240 : for (const txiter& ancestorIt : setAncestors) {
964 52550 : nSizeCheck += ancestorIt->GetTxSize();
965 52550 : nFeesCheck += ancestorIt->GetModifiedFee();
966 52550 : nSigOpCheck += ancestorIt->GetSigOpCount();
967 : }
968 :
969 3077690 : assert(it->GetCountWithAncestors() == nCountCheck);
970 3077690 : assert(it->GetSizeWithAncestors() == nSizeCheck);
971 3077690 : assert(it->GetSigOpCountWithAncestors() == nSigOpCheck);
972 3077690 : assert(it->GetModFeesWithAncestors() == nFeesCheck);
973 :
974 : // Check children against mapNextTx
975 6155380 : CTxMemPool::setEntries setChildrenCheck;
976 3077690 : auto iter = mapNextTx.lower_bound(COutPoint(it->GetTx().GetHash(), 0));
977 3077690 : int64_t childSizes = 0;
978 3112740 : for (; iter != mapNextTx.end() && iter->first->hash == tx.GetHash(); ++iter) {
979 35050 : txiter childit = mapTx.find(iter->second->GetHash());
980 35050 : assert(childit != mapTx.end()); // mapNextTx points to in-mempool transactions
981 35050 : if (setChildrenCheck.insert(childit).second) {
982 35050 : childSizes += childit->GetTxSize();
983 : }
984 : }
985 3077690 : 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 3077690 : assert(it->GetSizeWithDescendants() >= (uint64_t)(childSizes + it->GetTxSize()));
989 :
990 :
991 3077690 : if (fDependsWait)
992 29857 : waitingOnDependants.push_back(&(*it));
993 : else {
994 6095660 : CValidationState state;
995 3047830 : PrecomputedTransactionData precomTxData(tx);
996 3047830 : assert(CheckInputs(tx, state, mempoolDuplicate, false, 0, false, precomTxData, nullptr));
997 3047830 : UpdateCoins(tx, mempoolDuplicate, 1000000);
998 : }
999 : }
1000 :
1001 48176 : unsigned int stepsSinceLastRemove = 0;
1002 83779 : while (!waitingOnDependants.empty()) {
1003 35603 : const CTxMemPoolEntry* entry = waitingOnDependants.front();
1004 35603 : waitingOnDependants.pop_front();
1005 71206 : CValidationState state;
1006 35603 : if (!mempoolDuplicate.HaveInputs(entry->GetTx())) {
1007 5746 : waitingOnDependants.push_back(entry);
1008 5746 : stepsSinceLastRemove++;
1009 5746 : assert(stepsSinceLastRemove < waitingOnDependants.size());
1010 : } else {
1011 29857 : PrecomputedTransactionData precomTxData(entry->GetTx());
1012 29857 : assert(CheckInputs(entry->GetTx(), state, mempoolDuplicate, false, 0, false, precomTxData, nullptr));
1013 29857 : UpdateCoins(entry->GetTx(), mempoolDuplicate, 1000000);
1014 29857 : stepsSinceLastRemove = 0;
1015 : }
1016 : }
1017 4313600 : for (auto it = mapNextTx.cbegin(); it != mapNextTx.cend(); it++) {
1018 4265430 : const uint256& hash = it->second->GetHash();
1019 4265430 : indexed_transaction_set::const_iterator it2 = mapTx.find(hash);
1020 8530860 : const CTransactionRef& tx = it2->GetSharedTx();
1021 4265430 : assert(it2 != mapTx.end());
1022 4265430 : assert(tx == it->second);
1023 : }
1024 :
1025 : // Consistency check for sapling nullifiers
1026 48176 : checkNullifiers();
1027 :
1028 48176 : assert(totalTxSize == checkTotal);
1029 48176 : assert(innerUsage == cachedInnerUsage);
1030 : }
1031 :
1032 48176 : void CTxMemPool::checkNullifiers() const
1033 : {
1034 48297 : for (const auto& it : mapSaplingNullifiers) {
1035 121 : const uint256& hash = it.second->GetHash();
1036 121 : const auto& findTx = mapTx.find(hash);
1037 121 : assert(findTx != mapTx.end());
1038 242 : const CTransactionRef& tx = findTx->GetSharedTx();
1039 121 : assert(*tx == *it.second);
1040 : }
1041 48176 : }
1042 :
1043 117409 : bool CTxMemPool::CompareDepthAndScore(const uint256& hasha, const uint256& hashb)
1044 : {
1045 234818 : LOCK(cs);
1046 117409 : indexed_transaction_set::const_iterator i = mapTx.find(hasha);
1047 117409 : if (i == mapTx.end()) return false;
1048 102039 : indexed_transaction_set::const_iterator j = mapTx.find(hashb);
1049 102039 : if (j == mapTx.end()) return true;
1050 99869 : uint64_t counta = i->GetCountWithAncestors();
1051 99869 : uint64_t countb = j->GetCountWithAncestors();
1052 99869 : if (counta == countb) {
1053 99841 : return CompareTxMemPoolEntryByScore()(*i, *j);
1054 : }
1055 28 : return counta < countb;
1056 : }
1057 :
1058 : namespace {
1059 : class DepthAndScoreComparator
1060 : {
1061 : public:
1062 26124300 : bool operator()(const CTxMemPool::indexed_transaction_set::const_iterator& a, const CTxMemPool::indexed_transaction_set::const_iterator& b) const
1063 : {
1064 26124300 : uint64_t counta = a->GetCountWithAncestors();
1065 26124300 : uint64_t countb = b->GetCountWithAncestors();
1066 26124300 : if (counta == countb) {
1067 26123800 : return CompareTxMemPoolEntryByScore()(*a, *b);
1068 : }
1069 420 : return counta < countb;
1070 : }
1071 : };
1072 : }
1073 :
1074 11430 : std::vector<CTxMemPool::indexed_transaction_set::const_iterator> CTxMemPool::GetSortedDepthAndScore() const
1075 : {
1076 11430 : std::vector<indexed_transaction_set::const_iterator> iters;
1077 11430 : AssertLockHeld(cs);
1078 :
1079 11430 : iters.reserve(mapTx.size());
1080 :
1081 5140350 : for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi) {
1082 2558740 : iters.push_back(mi);
1083 : }
1084 11430 : std::sort(iters.begin(), iters.end(), DepthAndScoreComparator());
1085 11430 : return iters;
1086 : }
1087 :
1088 11083 : void CTxMemPool::queryHashes(std::vector<uint256>& vtxid)
1089 : {
1090 11083 : LOCK(cs);
1091 22166 : auto iters = GetSortedDepthAndScore();
1092 :
1093 11083 : vtxid.clear();
1094 11083 : vtxid.reserve(mapTx.size());
1095 :
1096 2568980 : for (auto it : iters) {
1097 2557900 : vtxid.emplace_back(it->GetTx().GetHash());
1098 : }
1099 11083 : }
1100 :
1101 23989 : static TxMempoolInfo GetInfo(CTxMemPool::indexed_transaction_set::const_iterator it) {
1102 23989 : 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 1192 : for (auto it : iters) {
1113 1690 : 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 1258613 : std::shared_ptr<const CTransaction> CTxMemPool::get(const uint256& hash) const
1129 : {
1130 2517226 : LOCK(cs);
1131 1258613 : indexed_transaction_set::const_iterator i = mapTx.find(hash);
1132 1258613 : if (i == mapTx.end())
1133 1211030 : return nullptr;
1134 1306196 : return i->GetSharedTx();
1135 : }
1136 :
1137 26656 : TxMempoolInfo CTxMemPool::info(const uint256& hash) const
1138 : {
1139 53312 : LOCK(cs);
1140 26656 : indexed_transaction_set::const_iterator i = mapTx.find(hash);
1141 26656 : if (i == mapTx.end())
1142 26656 : return TxMempoolInfo();
1143 23144 : return GetInfo(i);
1144 : }
1145 :
1146 178055 : bool CTxMemPool::existsProviderTxConflict(const CTransaction &tx) const
1147 : {
1148 180240 : if (!tx.IsSpecialTx()) return false;
1149 :
1150 178429 : LOCK(cs);
1151 :
1152 374 : switch(tx.nType) {
1153 332 : case CTransaction::TxType::PROREG: {
1154 664 : ProRegPL pl;
1155 332 : 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 665 : if (mapProTxAddresses.count(pl.addr) || mapProTxPubKeyIDs.count(pl.keyIDOwner) ||
1160 660 : mapProTxBlsPubKeyHashes.count(pl.pubKeyOperator.GetHash())) {
1161 3 : return true;
1162 : }
1163 4843 : if (!pl.collateralOutpoint.hash.IsNull()) {
1164 194 : if (mapProTxCollaterals.count(pl.collateralOutpoint)) {
1165 : // there is another ProRegTx that refers to the same collateral
1166 0 : return true;
1167 : }
1168 388 : 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 13 : case CTransaction::TxType::PROUPSERV: {
1177 26 : ProUpServPL pl;
1178 13 : 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 13 : auto it = mapProTxAddresses.find(pl.addr);
1183 13 : return it != mapProTxAddresses.end() && it->second != pl.proTxHash;
1184 : }
1185 :
1186 21 : case CTransaction::TxType::PROUPREG: {
1187 42 : ProUpRegPL pl;
1188 21 : 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 21 : auto it = mapProTxBlsPubKeyHashes.find(pl.pubKeyOperator.GetHash());
1193 21 : 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 983 : CFeeRate CTxMemPool::estimateSmartFee(int nBlocks, int *answerFoundAtBlocks) const
1207 : {
1208 983 : LOCK(cs);
1209 1966 : 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 168976 : void CTxMemPool::ApplyDelta(const uint256& hash, CAmount& nFeeDelta) const
1266 : {
1267 168977 : LOCK(cs);
1268 168976 : std::map<uint256, CAmount>::const_iterator pos = mapDeltas.find(hash);
1269 168976 : if (pos == mapDeltas.end())
1270 337950 : return;
1271 1 : const CAmount &delta = pos->second;
1272 1 : nFeeDelta += delta;
1273 : }
1274 :
1275 317171 : void CTxMemPool::ClearPrioritisation(const uint256 hash)
1276 : {
1277 317171 : LOCK(cs);
1278 317171 : mapDeltas.erase(hash);
1279 317171 : }
1280 :
1281 274 : bool CTxMemPool::nullifierExists(const uint256& nullifier) const
1282 : {
1283 274 : LOCK(cs);
1284 548 : return mapSaplingNullifiers.count(nullifier);
1285 : }
1286 :
1287 119378 : bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const
1288 : {
1289 119378 : if (tx.HasZerocoinSpendInputs())
1290 : return true;
1291 344055 : for (unsigned int i = 0; i < tx.vin.size(); i++)
1292 224746 : if (exists(tx.vin[i].prevout.hash))
1293 : return false;
1294 : return true;
1295 : }
1296 :
1297 :
1298 280826 : CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView* baseIn, CTxMemPool& mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) {}
1299 :
1300 1037770 : 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 2075550 : CTransactionRef ptx = mempool.get(outpoint.hash);
1306 1037770 : if (ptx) {
1307 30824 : if (outpoint.n < ptx->vout.size()) {
1308 30824 : coin = Coin(ptx->vout[outpoint.n], MEMPOOL_HEIGHT, false, false);
1309 30824 : return true;
1310 : } else {
1311 : return false;
1312 : }
1313 : }
1314 1006947 : 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 136 : bool CCoinsViewMemPool::GetNullifier(const uint256& nullifier) const
1323 : {
1324 136 : return mempool.nullifierExists(nullifier) || base->GetNullifier(nullifier);
1325 : }
1326 :
1327 562486 : size_t CTxMemPool::DynamicMemoryUsage() const
1328 : {
1329 562486 : 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 562486 : return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 15 * sizeof(void*)) * mapTx.size() +
1333 562486 : memusage::DynamicUsage(mapNextTx) +
1334 562486 : memusage::DynamicUsage(mapDeltas) +
1335 562486 : memusage::DynamicUsage(mapLinks) +
1336 562486 : cachedInnerUsage +
1337 562486 : memusage::DynamicUsage(mapSaplingNullifiers);
1338 : }
1339 :
1340 321986 : void CTxMemPool::RemoveStaged(setEntries &stage, bool updateDescendants, MemPoolRemovalReason reason)
1341 : {
1342 321986 : AssertLockHeld(cs);
1343 321986 : UpdateForRemoveFromMempool(stage, updateDescendants);
1344 508883 : for (const txiter& it : stage) {
1345 186897 : removeUnchecked(it, reason);
1346 : }
1347 321986 : }
1348 :
1349 119499 : int CTxMemPool::Expire(int64_t time)
1350 : {
1351 119499 : LOCK(cs);
1352 119499 : indexed_transaction_set::index<entry_time>::type::iterator it = mapTx.get<entry_time>().begin();
1353 238998 : setEntries toremove;
1354 119499 : while (it != mapTx.get<entry_time>().end() && it->GetTime() < time) {
1355 0 : toremove.insert(mapTx.project<0>(it));
1356 0 : it++;
1357 : }
1358 238998 : setEntries stage;
1359 119499 : for (const txiter& removeit : toremove) {
1360 0 : CalculateDescendants(removeit, stage);
1361 : }
1362 119499 : RemoveStaged(stage, false, MemPoolRemovalReason::EXPIRY);
1363 238998 : 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 42628 : void CTxMemPool::UpdateChild(txiter entry, txiter child, bool add)
1377 : {
1378 42628 : setEntries s;
1379 42628 : if (add && mapLinks[entry].children.insert(child).second) {
1380 42607 : cachedInnerUsage += memusage::IncrementalDynamicUsage(s);
1381 21 : } else if (!add && mapLinks[entry].children.erase(child)) {
1382 21 : cachedInnerUsage -= memusage::IncrementalDynamicUsage(s);
1383 : }
1384 42628 : }
1385 :
1386 81932 : void CTxMemPool::UpdateParent(txiter entry, txiter parent, bool add)
1387 : {
1388 81932 : setEntries s;
1389 81932 : if (add && mapLinks[entry].parents.insert(parent).second) {
1390 42607 : cachedInnerUsage += memusage::IncrementalDynamicUsage(s);
1391 39325 : } else if (!add && mapLinks[entry].parents.erase(parent)) {
1392 39325 : cachedInnerUsage -= memusage::IncrementalDynamicUsage(s);
1393 : }
1394 81932 : }
1395 :
1396 6456470 : const CTxMemPool::setEntries & CTxMemPool::GetMemPoolParents(txiter entry) const
1397 : {
1398 6456470 : assert (entry != mapTx.end());
1399 6456470 : txlinksMap::const_iterator it = mapLinks.find(entry);
1400 6456470 : assert(it != mapLinks.end());
1401 6456470 : return it->second.parents;
1402 : }
1403 :
1404 6366350 : const CTxMemPool::setEntries & CTxMemPool::GetMemPoolChildren(txiter entry) const
1405 : {
1406 6366350 : assert (entry != mapTx.end());
1407 6366350 : txlinksMap::const_iterator it = mapLinks.find(entry);
1408 6366350 : assert(it != mapLinks.end());
1409 6366350 : return it->second.children;
1410 : }
1411 :
1412 1378 : CFeeRate CTxMemPool::GetMinFee(size_t sizelimit) const
1413 : {
1414 2756 : LOCK(cs);
1415 1378 : if (!blockSinceLastRollingFeeBump || rollingMinimumFeeRate == 0)
1416 1373 : 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 8 : void CTxMemPool::trackPackageRemoved(const CFeeRate& rate)
1438 : {
1439 8 : AssertLockHeld(cs);
1440 8 : if (rate.GetFeePerK() > rollingMinimumFeeRate) {
1441 6 : rollingMinimumFeeRate = rate.GetFeePerK();
1442 6 : blockSinceLastRollingFeeBump = false;
1443 : }
1444 8 : }
1445 :
1446 290637 : void CTxMemPool::TrimToSize(size_t sizelimit, std::vector<COutPoint>* pvNoSpendsRemaining)
1447 : {
1448 290637 : LOCK(cs);
1449 290637 : unsigned nTxnRemoved = 0;
1450 290637 : CFeeRate maxFeeRateRemoved(0);
1451 290645 : while (DynamicMemoryUsage() > sizelimit) {
1452 8 : 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 8 : CFeeRate removed(it->GetModFeesWithDescendants(), it->GetSizeWithDescendants());
1459 8 : removed += minReasonableRelayFee;
1460 8 : trackPackageRemoved(removed);
1461 8 : maxFeeRateRemoved = std::max(maxFeeRateRemoved, removed);
1462 :
1463 16 : setEntries stage;
1464 8 : CalculateDescendants(mapTx.project<0>(it), stage);
1465 8 : nTxnRemoved += stage.size();
1466 :
1467 16 : std::vector<CTransaction> txn;
1468 8 : if (pvNoSpendsRemaining) {
1469 0 : txn.reserve(stage.size());
1470 0 : for (txiter it: stage)
1471 0 : txn.push_back(it->GetTx());
1472 : }
1473 8 : RemoveStaged(stage, false, MemPoolRemovalReason::SIZELIMIT);
1474 8 : 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 290637 : if (maxFeeRateRemoved > CFeeRate(0))
1487 10 : LogPrint(BCLog::MEMPOOL, "Removed %u txn, rolling minimum fee bumped to %s\n", nTxnRemoved, maxFeeRateRemoved.ToString());
1488 290637 : }
1489 :
1490 511880 : bool CTxMemPool::TransactionWithinChainLimit(const uint256& txid, size_t chainLimit) const {
1491 511880 : LOCK(cs);
1492 511880 : auto it = mapTx.find(txid);
1493 512195 : return it == mapTx.end() || (it->GetCountWithAncestors() < chainLimit &&
1494 512347 : 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 :
|