]> Git Repo - VerusCoin.git/blame - src/txmempool.cpp
Merge pull request #519 from jl777/dPoW
[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"
7e2cbee1 17#define _COINBASE_MATURITY 100
319b1160
GA
18
19using namespace std;
20
8bdd2877 21CTxMemPoolEntry::CTxMemPoolEntry():
bde5c8b0 22 nFee(0), nTxSize(0), nModSize(0), nUsageSize(0), nTime(0), dPriority(0.0), hadNoDependencies(false)
4d707d51
GA
23{
24 nHeight = MEMPOOL_HEIGHT;
25}
26
a372168e 27CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
4d707d51 28 int64_t _nTime, double _dPriority,
b649e039
AM
29 unsigned int _nHeight, bool poolHasNoInputsOf):
30 tx(_tx), nFee(_nFee), nTime(_nTime), dPriority(_dPriority), nHeight(_nHeight),
31 hadNoDependencies(poolHasNoInputsOf)
4d707d51
GA
32{
33 nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
c26649f9 34 nModSize = tx.CalculateModifiedSize(nTxSize);
6bd1d60c 35 nUsageSize = RecursiveDynamicUsage(tx);
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
58 fSanityCheck = false;
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);
b649e039
AM
100 mapTx[hash] = entry;
101 const CTransaction& tx = mapTx[hash].GetTx();
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;
143 const CTransaction& tx = mapTx[hash].GetTx();
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);
6f2c26a4 161 totalTxSize -= mapTx[hash].GetTxSize();
bde5c8b0 162 cachedInnerUsage -= mapTx[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
7a90b9dd 173 extern char ASSETCHAINS_SYMBOL[];
174 if ( ASSETCHAINS_SYMBOL[0] == 0 )
175 COINBASE_MATURITY = _COINBASE_MATURITY;
723d12c0
MC
176 LOCK(cs);
177 list<CTransaction> transactionsToRemove;
178 for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
179 const CTransaction& tx = it->second.GetTx();
180 BOOST_FOREACH(const CTxIn& txin, tx.vin) {
181 std::map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(txin.prevout.hash);
182 if (it2 != mapTx.end())
183 continue;
184 const CCoins *coins = pcoins->AccessCoins(txin.prevout.hash);
185 if (fSanityCheck) assert(coins);
a79c8e24 186 if (!coins || (coins->IsCoinBase() && ((signed long)nMemPoolHeight) - coins->nHeight < COINBASE_MATURITY)) {
723d12c0
MC
187 transactionsToRemove.push_back(tx);
188 break;
189 }
190 }
191 }
192 BOOST_FOREACH(const CTransaction& tx, transactionsToRemove) {
193 list<CTransaction> removed;
194 remove(tx, removed, true);
195 }
196}
197
a8ac403d
SB
198
199void CTxMemPool::removeWithAnchor(const uint256 &invalidRoot)
200{
201 // If a block is disconnected from the tip, and the root changed,
202 // we must invalidate transactions from the mempool which spend
203 // from that root -- almost as though they were spending coinbases
204 // which are no longer valid to spend due to coinbase maturity.
205 LOCK(cs);
206 list<CTransaction> transactionsToRemove;
207
208 for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
209 const CTransaction& tx = it->second.GetTx();
b7e4abd6
SB
210 BOOST_FOREACH(const JSDescription& joinsplit, tx.vjoinsplit) {
211 if (joinsplit.anchor == invalidRoot) {
a8ac403d
SB
212 transactionsToRemove.push_back(tx);
213 break;
214 }
215 }
216 }
217
218 BOOST_FOREACH(const CTransaction& tx, transactionsToRemove) {
219 list<CTransaction> removed;
220 remove(tx, removed, true);
221 }
222}
223
93a18a36 224void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed)
319b1160
GA
225{
226 // Remove transactions which depend on inputs of tx, recursively
98e84aae 227 list<CTransaction> result;
319b1160
GA
228 LOCK(cs);
229 BOOST_FOREACH(const CTxIn &txin, tx.vin) {
230 std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(txin.prevout);
231 if (it != mapNextTx.end()) {
232 const CTransaction &txConflict = *it->second.ptx;
233 if (txConflict != tx)
93a18a36
GA
234 {
235 remove(txConflict, removed, true);
236 }
319b1160
GA
237 }
238 }
d66877af 239
b7e4abd6 240 BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
22de1602
SB
241 BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) {
242 std::map<uint256, const CTransaction*>::iterator it = mapNullifiers.find(nf);
bb64be52 243 if (it != mapNullifiers.end()) {
d66877af
SB
244 const CTransaction &txConflict = *it->second;
245 if (txConflict != tx)
246 {
247 remove(txConflict, removed, true);
248 }
249 }
250 }
251 }
319b1160
GA
252}
253
7329fdd1
MF
254/**
255 * Called when a block is connected. Removes from mempool and updates the miner fee estimator.
256 */
171ca774 257void CTxMemPool::removeForBlock(const std::vector<CTransaction>& vtx, unsigned int nBlockHeight,
b649e039 258 std::list<CTransaction>& conflicts, bool fCurrentEstimate)
171ca774
GA
259{
260 LOCK(cs);
261 std::vector<CTxMemPoolEntry> entries;
262 BOOST_FOREACH(const CTransaction& tx, vtx)
263 {
805344dc 264 uint256 hash = tx.GetHash();
171ca774
GA
265 if (mapTx.count(hash))
266 entries.push_back(mapTx[hash]);
267 }
171ca774
GA
268 BOOST_FOREACH(const CTransaction& tx, vtx)
269 {
270 std::list<CTransaction> dummy;
271 remove(tx, dummy, false);
272 removeConflicts(tx, conflicts);
805344dc 273 ClearPrioritisation(tx.GetHash());
171ca774 274 }
b649e039
AM
275 // After the txs in the new block have been removed from the mempool, update policy estimates
276 minerPolicyEstimator->processBlock(nBlockHeight, entries, fCurrentEstimate);
171ca774
GA
277}
278
319b1160
GA
279void CTxMemPool::clear()
280{
281 LOCK(cs);
282 mapTx.clear();
283 mapNextTx.clear();
6f2c26a4 284 totalTxSize = 0;
bde5c8b0 285 cachedInnerUsage = 0;
319b1160
GA
286 ++nTransactionsUpdated;
287}
288
d0867acb 289void CTxMemPool::check(const CCoinsViewCache *pcoins) const
319b1160
GA
290{
291 if (!fSanityCheck)
292 return;
293
294 LogPrint("mempool", "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
295
6f2c26a4 296 uint64_t checkTotal = 0;
bde5c8b0 297 uint64_t innerUsage = 0;
6f2c26a4 298
b7b4318f
MC
299 CCoinsViewCache mempoolDuplicate(const_cast<CCoinsViewCache*>(pcoins));
300
319b1160 301 LOCK(cs);
b7b4318f 302 list<const CTxMemPoolEntry*> waitingOnDependants;
4d707d51 303 for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
319b1160 304 unsigned int i = 0;
6f2c26a4 305 checkTotal += it->second.GetTxSize();
bde5c8b0 306 innerUsage += it->second.DynamicMemoryUsage();
4d707d51 307 const CTransaction& tx = it->second.GetTx();
b7b4318f 308 bool fDependsWait = false;
4d707d51 309 BOOST_FOREACH(const CTxIn &txin, tx.vin) {
319b1160 310 // Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
4d707d51 311 std::map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(txin.prevout.hash);
319b1160 312 if (it2 != mapTx.end()) {
4d707d51
GA
313 const CTransaction& tx2 = it2->second.GetTx();
314 assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
b7b4318f 315 fDependsWait = true;
319b1160 316 } else {
629d75fa
PW
317 const CCoins* coins = pcoins->AccessCoins(txin.prevout.hash);
318 assert(coins && coins->IsAvailable(txin.prevout.n));
319b1160
GA
319 }
320 // Check whether its inputs are marked in mapNextTx.
321 std::map<COutPoint, CInPoint>::const_iterator it3 = mapNextTx.find(txin.prevout);
322 assert(it3 != mapNextTx.end());
4d707d51 323 assert(it3->second.ptx == &tx);
319b1160
GA
324 assert(it3->second.n == i);
325 i++;
326 }
a667caec
SB
327
328 boost::unordered_map<uint256, ZCIncrementalMerkleTree, CCoinsKeyHasher> intermediates;
329
b7e4abd6 330 BOOST_FOREACH(const JSDescription &joinsplit, tx.vjoinsplit) {
22de1602
SB
331 BOOST_FOREACH(const uint256 &nf, joinsplit.nullifiers) {
332 assert(!pcoins->GetNullifier(nf));
d66877af
SB
333 }
334
434f3284 335 ZCIncrementalMerkleTree tree;
b7e4abd6 336 auto it = intermediates.find(joinsplit.anchor);
a667caec
SB
337 if (it != intermediates.end()) {
338 tree = it->second;
339 } else {
b7e4abd6 340 assert(pcoins->GetAnchorAt(joinsplit.anchor, tree));
a667caec
SB
341 }
342
b7e4abd6 343 BOOST_FOREACH(const uint256& commitment, joinsplit.commitments)
a667caec
SB
344 {
345 tree.append(commitment);
346 }
347
348 intermediates.insert(std::make_pair(tree.root(), tree));
d66877af 349 }
b7b4318f
MC
350 if (fDependsWait)
351 waitingOnDependants.push_back(&it->second);
352 else {
d7621ccf 353 CValidationState state;
c0dde76d 354 assert(ContextualCheckInputs(tx, state, mempoolDuplicate, false, 0, false, Params().GetConsensus(), NULL));
d7621ccf 355 UpdateCoins(tx, state, mempoolDuplicate, 1000000);
b7b4318f
MC
356 }
357 }
358 unsigned int stepsSinceLastRemove = 0;
359 while (!waitingOnDependants.empty()) {
360 const CTxMemPoolEntry* entry = waitingOnDependants.front();
361 waitingOnDependants.pop_front();
362 CValidationState state;
363 if (!mempoolDuplicate.HaveInputs(entry->GetTx())) {
364 waitingOnDependants.push_back(entry);
365 stepsSinceLastRemove++;
366 assert(stepsSinceLastRemove < waitingOnDependants.size());
367 } else {
c0dde76d 368 assert(ContextualCheckInputs(entry->GetTx(), state, mempoolDuplicate, false, 0, false, Params().GetConsensus(), NULL));
d7621ccf 369 UpdateCoins(entry->GetTx(), state, mempoolDuplicate, 1000000);
b7b4318f
MC
370 stepsSinceLastRemove = 0;
371 }
319b1160
GA
372 }
373 for (std::map<COutPoint, CInPoint>::const_iterator it = mapNextTx.begin(); it != mapNextTx.end(); it++) {
805344dc 374 uint256 hash = it->second.ptx->GetHash();
4d707d51
GA
375 map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(hash);
376 const CTransaction& tx = it2->second.GetTx();
319b1160 377 assert(it2 != mapTx.end());
4d707d51
GA
378 assert(&tx == it->second.ptx);
379 assert(tx.vin.size() > it->second.n);
319b1160
GA
380 assert(it->first == it->second.ptx->vin[it->second.n].prevout);
381 }
6f2c26a4 382
bb64be52 383 for (std::map<uint256, const CTransaction*>::const_iterator it = mapNullifiers.begin(); it != mapNullifiers.end(); it++) {
805344dc 384 uint256 hash = it->second->GetHash();
d66877af
SB
385 map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(hash);
386 const CTransaction& tx = it2->second.GetTx();
387 assert(it2 != mapTx.end());
388 assert(&tx == it->second);
389 }
390
6f2c26a4 391 assert(totalTxSize == checkTotal);
bde5c8b0 392 assert(innerUsage == cachedInnerUsage);
319b1160
GA
393}
394
4d707d51 395void CTxMemPool::queryHashes(vector<uint256>& vtxid)
319b1160
GA
396{
397 vtxid.clear();
398
399 LOCK(cs);
400 vtxid.reserve(mapTx.size());
4d707d51 401 for (map<uint256, CTxMemPoolEntry>::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi)
319b1160
GA
402 vtxid.push_back((*mi).first);
403}
404
405bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const
406{
407 LOCK(cs);
4d707d51 408 map<uint256, CTxMemPoolEntry>::const_iterator i = mapTx.find(hash);
319b1160 409 if (i == mapTx.end()) return false;
4d707d51 410 result = i->second.GetTx();
319b1160
GA
411 return true;
412}
a0fa20a1 413
171ca774
GA
414CFeeRate CTxMemPool::estimateFee(int nBlocks) const
415{
416 LOCK(cs);
417 return minerPolicyEstimator->estimateFee(nBlocks);
418}
419double CTxMemPool::estimatePriority(int nBlocks) const
420{
421 LOCK(cs);
422 return minerPolicyEstimator->estimatePriority(nBlocks);
423}
424
425bool
426CTxMemPool::WriteFeeEstimates(CAutoFile& fileout) const
427{
428 try {
429 LOCK(cs);
b649e039 430 fileout << 109900; // version required to read: 0.10.99 or later
171ca774
GA
431 fileout << CLIENT_VERSION; // version that wrote the file
432 minerPolicyEstimator->Write(fileout);
433 }
27df4123 434 catch (const std::exception&) {
7ff9d122 435 LogPrintf("CTxMemPool::WriteFeeEstimates(): unable to write policy estimator data (non-fatal)\n");
171ca774
GA
436 return false;
437 }
438 return true;
439}
440
441bool
442CTxMemPool::ReadFeeEstimates(CAutoFile& filein)
443{
444 try {
445 int nVersionRequired, nVersionThatWrote;
446 filein >> nVersionRequired >> nVersionThatWrote;
447 if (nVersionRequired > CLIENT_VERSION)
5262fde0 448 return error("CTxMemPool::ReadFeeEstimates(): up-version (%d) fee estimate file", nVersionRequired);
171ca774
GA
449
450 LOCK(cs);
b649e039 451 minerPolicyEstimator->Read(filein);
171ca774 452 }
27df4123 453 catch (const std::exception&) {
7ff9d122 454 LogPrintf("CTxMemPool::ReadFeeEstimates(): unable to read policy estimator data (non-fatal)\n");
171ca774
GA
455 return false;
456 }
457 return true;
458}
459
a372168e 460void CTxMemPool::PrioritiseTransaction(const uint256 hash, const string strHash, double dPriorityDelta, const CAmount& nFeeDelta)
2a72d459
LD
461{
462 {
463 LOCK(cs);
a372168e 464 std::pair<double, CAmount> &deltas = mapDeltas[hash];
2a72d459
LD
465 deltas.first += dPriorityDelta;
466 deltas.second += nFeeDelta;
467 }
a372168e 468 LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash, dPriorityDelta, FormatMoney(nFeeDelta));
2a72d459
LD
469}
470
a372168e 471void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, CAmount &nFeeDelta)
2a72d459
LD
472{
473 LOCK(cs);
a372168e 474 std::map<uint256, std::pair<double, CAmount> >::iterator pos = mapDeltas.find(hash);
2a72d459
LD
475 if (pos == mapDeltas.end())
476 return;
a372168e 477 const std::pair<double, CAmount> &deltas = pos->second;
2a72d459
LD
478 dPriorityDelta += deltas.first;
479 nFeeDelta += deltas.second;
480}
481
482void CTxMemPool::ClearPrioritisation(const uint256 hash)
483{
484 LOCK(cs);
485 mapDeltas.erase(hash);
486}
487
b649e039
AM
488bool CTxMemPool::HasNoInputsOf(const CTransaction &tx) const
489{
490 for (unsigned int i = 0; i < tx.vin.size(); i++)
491 if (exists(tx.vin[i].prevout.hash))
492 return false;
493 return true;
494}
171ca774 495
7c70438d 496CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { }
a0fa20a1 497
22de1602
SB
498bool CCoinsViewMemPool::GetNullifier(const uint256 &nf) const {
499 if (mempool.mapNullifiers.count(nf))
d66877af
SB
500 return true;
501
22de1602 502 return base->GetNullifier(nf);
d66877af
SB
503}
504
a3dc587a 505bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) const {
ad08d0b9
PW
506 // If an entry in the mempool exists, always return that one, as it's guaranteed to never
507 // conflict with the underlying cache, and it cannot have pruned entries (as it contains full)
508 // transactions. First checking the underlying cache risks returning a pruned entry instead.
a0fa20a1
PW
509 CTransaction tx;
510 if (mempool.lookup(txid, tx)) {
511 coins = CCoins(tx, MEMPOOL_HEIGHT);
512 return true;
513 }
ad08d0b9 514 return (base->GetCoins(txid, coins) && !coins.IsPruned());
a0fa20a1
PW
515}
516
a3dc587a 517bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) const {
a0fa20a1
PW
518 return mempool.exists(txid) || base->HaveCoins(txid);
519}
bde5c8b0
PW
520
521size_t CTxMemPool::DynamicMemoryUsage() const {
522 LOCK(cs);
523 return memusage::DynamicUsage(mapTx) + memusage::DynamicUsage(mapNextTx) + memusage::DynamicUsage(mapDeltas) + cachedInnerUsage;
524}
This page took 0.327782 seconds and 4 git commands to generate.