]> Git Repo - VerusCoin.git/blame - src/txmempool.cpp
Add failing test checking timelocked-txn removal during reorg
[VerusCoin.git] / src / txmempool.cpp
CommitLineData
319b1160 1// Copyright (c) 2009-2010 Satoshi Nakamoto
f914f1a7 2// Copyright (c) 2009-2014 The Bitcoin Core developers
7329fdd1 3// Distributed under the MIT software license, see the accompanying
319b1160
GA
4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
319b1160 6#include "txmempool.h"
611116d4 7
71697f97 8#include "clientversion.h"
691161d4 9#include "consensus/consensus.h"
da29ecbc 10#include "consensus/validation.h"
b7b4318f 11#include "main.h"
b649e039 12#include "policy/fees.h"
fa736190 13#include "streams.h"
ad49c256 14#include "util.h"
a372168e 15#include "utilmoneystr.h"
85c579e3 16#include "version.h"
319b1160
GA
17
18using namespace std;
19
8bdd2877 20CTxMemPoolEntry::CTxMemPoolEntry():
bde5c8b0 21 nFee(0), nTxSize(0), nModSize(0), nUsageSize(0), nTime(0), dPriority(0.0), hadNoDependencies(false)
4d707d51
GA
22{
23 nHeight = MEMPOOL_HEIGHT;
24}
25
a372168e 26CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
4d707d51 27 int64_t _nTime, double _dPriority,
b649e039
AM
28 unsigned int _nHeight, bool poolHasNoInputsOf):
29 tx(_tx), nFee(_nFee), nTime(_nTime), dPriority(_dPriority), nHeight(_nHeight),
30 hadNoDependencies(poolHasNoInputsOf)
4d707d51
GA
31{
32 nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
c26649f9 33 nModSize = tx.CalculateModifiedSize(nTxSize);
6bd1d60c 34 nUsageSize = RecursiveDynamicUsage(tx);
e328fa32 35 feeRate = CFeeRate(nFee, nTxSize);
4d707d51
GA
36}
37
38CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other)
39{
40 *this = other;
41}
42
43double
44CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const
45{
a372168e 46 CAmount nValueIn = tx.GetValueOut()+nFee;
c26649f9 47 double deltaPriority = ((double)(currentHeight-nHeight)*nValueIn)/nModSize;
4d707d51
GA
48 double dResult = dPriority + deltaPriority;
49 return dResult;
50}
51
8bdd2877 52CTxMemPool::CTxMemPool(const CFeeRate& _minRelayFee) :
b649e039 53 nTransactionsUpdated(0)
319b1160
GA
54{
55 // Sanity checks off by default for performance, because otherwise
56 // accepting transactions becomes O(N^2) where N is the number
57 // of transactions in the pool
934fd197 58 nCheckFrequency = 0;
171ca774 59
b649e039 60 minerPolicyEstimator = new CBlockPolicyEstimator(_minRelayFee);
171ca774
GA
61}
62
63CTxMemPool::~CTxMemPool()
64{
65 delete minerPolicyEstimator;
319b1160
GA
66}
67
68void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins)
69{
70 LOCK(cs);
71
72 std::map<COutPoint, CInPoint>::iterator it = mapNextTx.lower_bound(COutPoint(hashTx, 0));
73
74 // iterate over all COutPoints in mapNextTx whose hash equals the provided hashTx
75 while (it != mapNextTx.end() && it->first.hash == hashTx) {
76 coins.Spend(it->first.n); // and remove those outputs from coins
77 it++;
78 }
79}
80
81unsigned int CTxMemPool::GetTransactionsUpdated() const
82{
83 LOCK(cs);
84 return nTransactionsUpdated;
85}
86
87void CTxMemPool::AddTransactionsUpdated(unsigned int n)
88{
89 LOCK(cs);
90 nTransactionsUpdated += n;
91}
92
93
b649e039 94bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, bool fCurrentEstimate)
319b1160
GA
95{
96 // Add to memory pool without checking anything.
97 // Used by main.cpp AcceptToMemoryPool(), which DOES do
98 // all the appropriate checks.
99 LOCK(cs);
e328fa32
AH
100 mapTx.insert(entry);
101 const CTransaction& tx = mapTx.find(hash)->GetTx();
b649e039
AM
102 for (unsigned int i = 0; i < tx.vin.size(); i++)
103 mapNextTx[tx.vin[i].prevout] = CInPoint(&tx, i);
b7e4abd6 104 BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
22de1602
SB
105 BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) {
106 mapNullifiers[nf] = &tx;
d66877af
SB
107 }
108 }
b649e039
AM
109 nTransactionsUpdated++;
110 totalTxSize += entry.GetTxSize();
bde5c8b0 111 cachedInnerUsage += entry.DynamicMemoryUsage();
b649e039
AM
112 minerPolicyEstimator->processTransaction(entry, fCurrentEstimate);
113
319b1160
GA
114 return true;
115}
116
117
7fd6219a 118void CTxMemPool::remove(const CTransaction &origTx, std::list<CTransaction>& removed, bool fRecursive)
319b1160
GA
119{
120 // Remove transaction from memory pool
121 {
122 LOCK(cs);
7fd6219a 123 std::deque<uint256> txToRemove;
805344dc
S
124 txToRemove.push_back(origTx.GetHash());
125 if (fRecursive && !mapTx.count(origTx.GetHash())) {
ad9e86dc
GA
126 // If recursively removing but origTx isn't in the mempool
127 // be sure to remove any children that are in the pool. This can
128 // happen during chain re-orgs if origTx isn't re-accepted into
129 // the mempool for any reason.
130 for (unsigned int i = 0; i < origTx.vout.size(); i++) {
805344dc 131 std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(COutPoint(origTx.GetHash(), i));
ad9e86dc
GA
132 if (it == mapNextTx.end())
133 continue;
805344dc 134 txToRemove.push_back(it->second.ptx->GetHash());
ad9e86dc
GA
135 }
136 }
7fd6219a 137 while (!txToRemove.empty())
319b1160 138 {
7fd6219a
MC
139 uint256 hash = txToRemove.front();
140 txToRemove.pop_front();
141 if (!mapTx.count(hash))
142 continue;
e328fa32 143 const CTransaction& tx = mapTx.find(hash)->GetTx();
7fd6219a
MC
144 if (fRecursive) {
145 for (unsigned int i = 0; i < tx.vout.size(); i++) {
146 std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(COutPoint(hash, i));
147 if (it == mapNextTx.end())
148 continue;
805344dc 149 txToRemove.push_back(it->second.ptx->GetHash());
7fd6219a
MC
150 }
151 }
319b1160
GA
152 BOOST_FOREACH(const CTxIn& txin, tx.vin)
153 mapNextTx.erase(txin.prevout);
b7e4abd6 154 BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) {
22de1602
SB
155 BOOST_FOREACH(const uint256& nf, joinsplit.nullifiers) {
156 mapNullifiers.erase(nf);
d66877af
SB
157 }
158 }
6f2c26a4 159
7fd6219a 160 removed.push_back(tx);
e328fa32
AH
161 totalTxSize -= mapTx.find(hash)->GetTxSize();
162 cachedInnerUsage -= mapTx.find(hash)->DynamicMemoryUsage();
319b1160
GA
163 mapTx.erase(hash);
164 nTransactionsUpdated++;
b649e039 165 minerPolicyEstimator->removeTx(hash);
319b1160
GA
166 }
167 }
319b1160
GA
168}
169
723d12c0
MC
170void CTxMemPool::removeCoinbaseSpends(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight)
171{
172 // Remove transactions spending a coinbase which are now immature
173 LOCK(cs);
174 list<CTransaction> transactionsToRemove;
e328fa32
AH
175 for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
176 const CTransaction& tx = it->GetTx();
723d12c0 177 BOOST_FOREACH(const CTxIn& txin, tx.vin) {
e328fa32 178 indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
723d12c0
MC
179 if (it2 != mapTx.end())
180 continue;
181 const CCoins *coins = pcoins->AccessCoins(txin.prevout.hash);
934fd197 182 if (nCheckFrequency != 0) assert(coins);
a79c8e24 183 if (!coins || (coins->IsCoinBase() && ((signed long)nMemPoolHeight) - coins->nHeight < COINBASE_MATURITY)) {
723d12c0
MC
184 transactionsToRemove.push_back(tx);
185 break;
186 }
187 }
188 }
189 BOOST_FOREACH(const CTransaction& tx, transactionsToRemove) {
190 list<CTransaction> removed;
191 remove(tx, removed, true);
192 }
193}
194
a8ac403d
SB
195
196void CTxMemPool::removeWithAnchor(const uint256 &invalidRoot)
197{
198 // If a block is disconnected from the tip, and the root changed,
199 // we must invalidate transactions from the mempool which spend
200 // from that root -- almost as though they were spending coinbases
201 // which are no longer valid to spend due to coinbase maturity.
202 LOCK(cs);
203 list<CTransaction> transactionsToRemove;
204
e328fa32
AH
205 for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
206 const CTransaction& tx = it->GetTx();
b7e4abd6
SB
207 BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) {
208 if (joinsplit.anchor == invalidRoot) {
a8ac403d
SB
209 transactionsToRemove.push_back(tx);
210 break;
211 }
212 }
213 }
214
215 BOOST_FOREACH(const CTransaction& tx, transactionsToRemove) {
216 list<CTransaction> removed;
217 remove(tx, removed, true);
218 }
219}
220
93a18a36 221void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed)
319b1160
GA
222{
223 // Remove transactions which depend on inputs of tx, recursively
98e84aae 224 list<CTransaction> result;
319b1160
GA
225 LOCK(cs);
226 BOOST_FOREACH(const CTxIn &txin, tx.vin) {
227 std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(txin.prevout);
228 if (it != mapNextTx.end()) {
229 const CTransaction &txConflict = *it->second.ptx;
230 if (txConflict != tx)
93a18a36
GA
231 {
232 remove(txConflict, removed, true);
233 }
319b1160
GA
234 }
235 }
d66877af 236
b7e4abd6 237 BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
22de1602
SB
238 BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) {
239 std::map<uint256, const CTransaction*>::iterator it = mapNullifiers.find(nf);
bb64be52 240 if (it != mapNullifiers.end()) {
d66877af
SB
241 const CTransaction &txConflict = *it->second;
242 if (txConflict != tx)
243 {
244 remove(txConflict, removed, true);
245 }
246 }
247 }
248 }
319b1160
GA
249}
250
7329fdd1
MF
251/**
252 * Called when a block is connected. Removes from mempool and updates the miner fee estimator.
253 */
171ca774 254void CTxMemPool::removeForBlock(const std::vector<CTransaction>& vtx, unsigned int nBlockHeight,
b649e039 255 std::list<CTransaction>& conflicts, bool fCurrentEstimate)
171ca774
GA
256{
257 LOCK(cs);
258 std::vector<CTxMemPoolEntry> entries;
259 BOOST_FOREACH(const CTransaction& tx, vtx)
260 {
805344dc 261 uint256 hash = tx.GetHash();
e328fa32
AH
262
263 indexed_transaction_set::iterator i = mapTx.find(hash);
264 if (i != mapTx.end())
265 entries.push_back(*i);
171ca774 266 }
171ca774
GA
267 BOOST_FOREACH(const CTransaction& tx, vtx)
268 {
269 std::list<CTransaction> dummy;
270 remove(tx, dummy, false);
271 removeConflicts(tx, conflicts);
805344dc 272 ClearPrioritisation(tx.GetHash());
171ca774 273 }
b649e039
AM
274 // After the txs in the new block have been removed from the mempool, update policy estimates
275 minerPolicyEstimator->processBlock(nBlockHeight, entries, fCurrentEstimate);
171ca774
GA
276}
277
319b1160
GA
278void CTxMemPool::clear()
279{
280 LOCK(cs);
281 mapTx.clear();
282 mapNextTx.clear();
6f2c26a4 283 totalTxSize = 0;
bde5c8b0 284 cachedInnerUsage = 0;
319b1160
GA
285 ++nTransactionsUpdated;
286}
287
d0867acb 288void CTxMemPool::check(const CCoinsViewCache *pcoins) const
319b1160 289{
934fd197
PW
290 if (nCheckFrequency == 0)
291 return;
292
293 if (insecure_rand() >= nCheckFrequency)
319b1160
GA
294 return;
295
296 LogPrint("mempool", "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
297
6f2c26a4 298 uint64_t checkTotal = 0;
bde5c8b0 299 uint64_t innerUsage = 0;
6f2c26a4 300
b7b4318f
MC
301 CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins));
302
319b1160 303 LOCK(cs);
b7b4318f 304 list<const CTxMemPoolEntry*> waitingOnDependants;
e328fa32 305 for (indexed_transaction_set::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
319b1160 306 unsigned int i = 0;
e328fa32
AH
307 checkTotal += it->GetTxSize();
308 innerUsage += it->DynamicMemoryUsage();
309 const CTransaction& tx = it->GetTx();
b7b4318f 310 bool fDependsWait = false;
4d707d51 311 BOOST_FOREACH(const CTxIn &txin, tx.vin) {
319b1160 312 // Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
e328fa32 313 indexed_transaction_set::const_iterator it2 = mapTx.find(txin.prevout.hash);
319b1160 314 if (it2 != mapTx.end()) {
e328fa32 315 const CTransaction& tx2 = it2->GetTx();
4d707d51 316 assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
b7b4318f 317 fDependsWait = true;
319b1160 318 } else {
629d75fa
PW
319 const CCoins* coins = pcoins->AccessCoins(txin.prevout.hash);
320 assert(coins && coins->IsAvailable(txin.prevout.n));
319b1160
GA
321 }
322 // Check whether its inputs are marked in mapNextTx.
323 std::map<COutPoint, CInPoint>::const_iterator it3 = mapNextTx.find(txin.prevout);
324 assert(it3 != mapNextTx.end());
4d707d51 325 assert(it3->second.ptx == &tx);
319b1160
GA
326 assert(it3->second.n == i);
327 i++;
328 }
a667caec
SB
329
330 boost::unordered_map<uint256, ZCIncrementalMerkleTree, CCoinsKeyHasher> intermediates;
331
b7e4abd6 332 BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
22de1602
SB
333 BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) {
334 assert(!pcoins->GetNullifier(nf));
d66877af
SB
335 }
336
434f3284 337 ZCIncrementalMerkleTree tree;
b7e4abd6 338 auto it = intermediates.find(joinsplit.anchor);
a667caec
SB
339 if (it != intermediates.end()) {
340 tree = it->second;
341 } else {
b7e4abd6 342 assert(pcoins->GetAnchorAt(joinsplit.anchor, tree));
a667caec
SB
343 }
344
b7e4abd6 345 BOOST_FOREACH(const uint256& commitment, joinsplit.commitments)
a667caec
SB
346 {
347 tree.append(commitment);
348 }
349
350 intermediates.insert(std::make_pair(tree.root(), tree));
d66877af 351 }
b7b4318f 352 if (fDependsWait)
e328fa32 353 waitingOnDependants.push_back(&(*it));
b7b4318f 354 else {
d7621ccf 355 CValidationState state;
c0dde76d 356 assert(ContextualCheckInputs(tx, state, mempoolDuplicate, false, 0, false, Params().GetConsensus(), NULL));
d7621ccf 357 UpdateCoins(tx, state, mempoolDuplicate, 1000000);
b7b4318f
MC
358 }
359 }
360 unsigned int stepsSinceLastRemove = 0;
361 while (!waitingOnDependants.empty()) {
362 const CTxMemPoolEntry* entry = waitingOnDependants.front();
363 waitingOnDependants.pop_front();
364 CValidationState state;
365 if (!mempoolDuplicate.HaveInputs(entry->GetTx())) {
366 waitingOnDependants.push_back(entry);
367 stepsSinceLastRemove++;
368 assert(stepsSinceLastRemove < waitingOnDependants.size());
369 } else {
c0dde76d 370 assert(ContextualCheckInputs(entry->GetTx(), state, mempoolDuplicate, false, 0, false, Params().GetConsensus(), NULL));
d7621ccf 371 UpdateCoins(entry->GetTx(), state, mempoolDuplicate, 1000000);
b7b4318f
MC
372 stepsSinceLastRemove = 0;
373 }
319b1160
GA
374 }
375 for (std::map<COutPoint, CInPoint>::const_iterator it = mapNextTx.begin(); it != mapNextTx.end(); it++) {
805344dc 376 uint256 hash = it->second.ptx->GetHash();
e328fa32
AH
377 indexed_transaction_set::const_iterator it2 = mapTx.find(hash);
378 const CTransaction& tx = it2->GetTx();
319b1160 379 assert(it2 != mapTx.end());
4d707d51
GA
380 assert(&tx == it->second.ptx);
381 assert(tx.vin.size() > it->second.n);
319b1160
GA
382 assert(it->first == it->second.ptx->vin[it->second.n].prevout);
383 }
6f2c26a4 384
bb64be52 385 for (std::map<uint256, const CTransaction*>::const_iterator it = mapNullifiers.begin(); it != mapNullifiers.end(); it++) {
805344dc 386 uint256 hash = it->second->GetHash();
e328fa32
AH
387 indexed_transaction_set::const_iterator it2 = mapTx.find(hash);
388 const CTransaction& tx = it2->GetTx();
d66877af
SB
389 assert(it2 != mapTx.end());
390 assert(&tx == it->second);
391 }
392
6f2c26a4 393 assert(totalTxSize == checkTotal);
bde5c8b0 394 assert(innerUsage == cachedInnerUsage);
319b1160
GA
395}
396
4d707d51 397void CTxMemPool::queryHashes(vector<uint256>& vtxid)
319b1160
GA
398{
399 vtxid.clear();
400
401 LOCK(cs);
402 vtxid.reserve(mapTx.size());
e328fa32
AH
403 for (indexed_transaction_set::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi)
404 vtxid.push_back(mi->GetTx().GetHash());
319b1160
GA
405}
406
407bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const
408{
409 LOCK(cs);
e328fa32 410 indexed_transaction_set::const_iterator i = mapTx.find(hash);
319b1160 411 if (i == mapTx.end()) return false;
e328fa32 412 result = i->GetTx();
319b1160
GA
413 return true;
414}
a0fa20a1 415
171ca774
GA
416CFeeRate CTxMemPool::estimateFee(int nBlocks) const
417{
418 LOCK(cs);
419 return minerPolicyEstimator->estimateFee(nBlocks);
420}
421double CTxMemPool::estimatePriority(int nBlocks) const
422{
423 LOCK(cs);
424 return minerPolicyEstimator->estimatePriority(nBlocks);
425}
426
427bool
428CTxMemPool::WriteFeeEstimates(CAutoFile& fileout) const
429{
430 try {
431 LOCK(cs);
b649e039 432 fileout << 109900; // version required to read: 0.10.99 or later
171ca774
GA
433 fileout << CLIENT_VERSION; // version that wrote the file
434 minerPolicyEstimator->Write(fileout);
435 }
27df4123 436 catch (const std::exception&) {
7ff9d122 437 LogPrintf("CTxMemPool::WriteFeeEstimates(): unable to write policy estimator data (non-fatal)\n");
171ca774
GA
438 return false;
439 }
440 return true;
441}
442
443bool
444CTxMemPool::ReadFeeEstimates(CAutoFile& filein)
445{
446 try {
447 int nVersionRequired, nVersionThatWrote;
448 filein >> nVersionRequired >> nVersionThatWrote;
449 if (nVersionRequired > CLIENT_VERSION)
5262fde0 450 return error("CTxMemPool::ReadFeeEstimates(): up-version (%d) fee estimate file", nVersionRequired);
171ca774
GA
451
452 LOCK(cs);
b649e039 453 minerPolicyEstimator->Read(filein);
171ca774 454 }
27df4123 455 catch (const std::exception&) {
7ff9d122 456 LogPrintf("CTxMemPool::ReadFeeEstimates(): unable to read policy estimator data (non-fatal)\n");
171ca774
GA
457 return false;
458 }
459 return true;
460}
461
a372168e 462void CTxMemPool::PrioritiseTransaction(const uint256 hash, const string strHash, double dPriorityDelta, const CAmount& nFeeDelta)
2a72d459
LD
463{
464 {
465 LOCK(cs);
a372168e 466 std::pair<double, CAmount> &deltas = mapDeltas[hash];
2a72d459
LD
467 deltas.first += dPriorityDelta;
468 deltas.second += nFeeDelta;
469 }
a372168e 470 LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash, dPriorityDelta, FormatMoney(nFeeDelta));
2a72d459
LD
471}
472
a372168e 473void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, CAmount &nFeeDelta)
2a72d459
LD
474{
475 LOCK(cs);
a372168e 476 std::map<uint256, std::pair<double, CAmount> >::iterator pos = mapDeltas.find(hash);
2a72d459
LD
477 if (pos == mapDeltas.end())
478 return;
a372168e 479 const std::pair<double, CAmount> &deltas = pos->second;
2a72d459
LD
480 dPriorityDelta += deltas.first;
481 nFeeDelta += deltas.second;
482}
483
484void CTxMemPool::ClearPrioritisation(const uint256 hash)
485{
486 LOCK(cs);
487 mapDeltas.erase(hash);
488}
489
b649e039
AM
490bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const
491{
492 for (unsigned int i = 0; i < tx.vin.size(); i++)
493 if (exists(tx.vin[i].prevout.hash))
494 return false;
495 return true;
496}
171ca774 497
7c70438d 498CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { }
a0fa20a1 499
22de1602
SB
500bool CCoinsViewMemPool::GetNullifier(const uint256 &nf) const {
501 if (mempool.mapNullifiers.count(nf))
d66877af
SB
502 return true;
503
22de1602 504 return base->GetNullifier(nf);
d66877af
SB
505}
506
a3dc587a 507bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) const {
ad08d0b9
PW
508 // If an entry in the mempool exists, always return that one, as it's guaranteed to never
509 // conflict with the underlying cache, and it cannot have pruned entries (as it contains full)
510 // transactions. First checking the underlying cache risks returning a pruned entry instead.
a0fa20a1
PW
511 CTransaction tx;
512 if (mempool.lookup(txid, tx)) {
513 coins = CCoins(tx, MEMPOOL_HEIGHT);
514 return true;
515 }
ad08d0b9 516 return (base->GetCoins(txid, coins) && !coins.IsPruned());
a0fa20a1
PW
517}
518
a3dc587a 519bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) const {
a0fa20a1
PW
520 return mempool.exists(txid) || base->HaveCoins(txid);
521}
bde5c8b0
PW
522
523size_t CTxMemPool::DynamicMemoryUsage() const {
524 LOCK(cs);
e328fa32
AH
525 // Estimate the overhead of mapTx to be 6 pointers + an allocation, as no exact formula for boost::multi_index_contained is implemented.
526 return memusage::MallocUsage(sizeof(CTxMemPoolEntry) + 6 * sizeof(void*)) * mapTx.size() + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + cachedInnerUsage;
bde5c8b0 527}
This page took 0.210646 seconds and 4 git commands to generate.