txmempool.cpp 22.4 KB
Newer Older
1
2
3
4
5
6
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "txmempool.h"
Philip Kaufmann's avatar
Philip Kaufmann committed
7
8

#include "core.h"
Wladimir J. van der Laan's avatar
Wladimir J. van der Laan committed
9
#include "util.h"
10

11
12
#include <boost/circular_buffer.hpp>

13
14
using namespace std;

15
CTxMemPoolEntry::CTxMemPoolEntry():
16
    nFee(0), nTxSize(0), nModSize(0), nTime(0), dPriority(0.0)
17
18
19
20
21
22
23
24
25
26
{
    nHeight = MEMPOOL_HEIGHT;
}

CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, int64_t _nFee,
                                 int64_t _nTime, double _dPriority,
                                 unsigned int _nHeight):
    tx(_tx), nFee(_nFee), nTime(_nTime), dPriority(_dPriority), nHeight(_nHeight)
{
    nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
27
28

    nModSize = tx.CalculateModifiedSize(nTxSize);
29
30
31
32
33
34
35
36
37
38
39
}

CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other)
{
    *this = other;
}

double
CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const
{
    int64_t nValueIn = tx.GetValueOut()+nFee;
40
    double deltaPriority = ((double)(currentHeight-nHeight)*nValueIn)/nModSize;
41
42
43
44
    double dResult = dPriority + deltaPriority;
    return dResult;
}

45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//
// Keep track of fee/priority for transactions confirmed within N blocks
//
class CBlockAverage
{
private:
    boost::circular_buffer<CFeeRate> feeSamples;
    boost::circular_buffer<double> prioritySamples;

    template<typename T> std::vector<T> buf2vec(boost::circular_buffer<T> buf) const
    {
        std::vector<T> vec(buf.begin(), buf.end());
        return vec;
    }

public:
    CBlockAverage() : feeSamples(100), prioritySamples(100) { }

    void RecordFee(const CFeeRate& feeRate) {
        feeSamples.push_back(feeRate);
    }

    void RecordPriority(double priority) {
        prioritySamples.push_back(priority);
    }

    size_t FeeSamples() const { return feeSamples.size(); }
    size_t GetFeeSamples(std::vector<CFeeRate>& insertInto) const
    {
        BOOST_FOREACH(const CFeeRate& f, feeSamples)
            insertInto.push_back(f);
        return feeSamples.size();
    }
    size_t PrioritySamples() const { return prioritySamples.size(); }
    size_t GetPrioritySamples(std::vector<double>& insertInto) const
    {
        BOOST_FOREACH(double d, prioritySamples)
            insertInto.push_back(d);
        return prioritySamples.size();
    }

    // Used as belt-and-suspenders check when reading to detect
    // file corruption
Gavin Andresen's avatar
Gavin Andresen committed
88
    bool AreSane(const std::vector<CFeeRate>& vecFee, const CFeeRate& minRelayFee)
89
90
91
92
93
    {
        BOOST_FOREACH(CFeeRate fee, vecFee)
        {
            if (fee < CFeeRate(0))
                return false;
Gavin Andresen's avatar
Gavin Andresen committed
94
            if (fee.GetFeePerK() > minRelayFee.GetFeePerK() * 10000)
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
                return false;
        }
        return true;
    }
    bool AreSane(const std::vector<double> vecPriority)
    {
        BOOST_FOREACH(double priority, vecPriority)
        {
            if (priority < 0)
                return false;
        }
        return true;
    }

    void Write(CAutoFile& fileout) const
    {
        std::vector<CFeeRate> vecFee = buf2vec(feeSamples);
        fileout << vecFee;
        std::vector<double> vecPriority = buf2vec(prioritySamples);
        fileout << vecPriority;
    }

Gavin Andresen's avatar
Gavin Andresen committed
117
    void Read(CAutoFile& filein, const CFeeRate& minRelayFee) {
118
119
        std::vector<CFeeRate> vecFee;
        filein >> vecFee;
Gavin Andresen's avatar
Gavin Andresen committed
120
        if (AreSane(vecFee, minRelayFee))
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
            feeSamples.insert(feeSamples.end(), vecFee.begin(), vecFee.end());
        else
            throw runtime_error("Corrupt fee value in estimates file.");
        std::vector<double> vecPriority;
        filein >> vecPriority;
        if (AreSane(vecPriority))
            prioritySamples.insert(prioritySamples.end(), vecPriority.begin(), vecPriority.end());
        else
            throw runtime_error("Corrupt priority value in estimates file.");
        if (feeSamples.size() + prioritySamples.size() > 0)
            LogPrint("estimatefee", "Read %d fee samples and %d priority samples\n",
                     feeSamples.size(), prioritySamples.size());
    }
};

class CMinerPolicyEstimator
{
private:
    // Records observed averages transactions that confirmed within one block, two blocks,
    // three blocks etc.
    std::vector<CBlockAverage> history;
    std::vector<CFeeRate> sortedFeeSamples;
    std::vector<double> sortedPrioritySamples;

    int nBestSeenHeight;

    // nBlocksAgo is 0 based, i.e. transactions that confirmed in the highest seen block are
    // nBlocksAgo == 0, transactions in the block before that are nBlocksAgo == 1 etc.
Gavin Andresen's avatar
Gavin Andresen committed
149
    void seenTxConfirm(const CFeeRate& feeRate, const CFeeRate& minRelayFee, double dPriority, int nBlocksAgo)
150
151
152
153
154
155
156
    {
        // Last entry records "everything else".
        int nBlocksTruncated = min(nBlocksAgo, (int) history.size() - 1);
        assert(nBlocksTruncated >= 0);

        // We need to guess why the transaction was included in a block-- either
        // because it is high-priority or because it has sufficient fees.
Gavin Andresen's avatar
Gavin Andresen committed
157
        bool sufficientFee = (feeRate > minRelayFee);
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
        bool sufficientPriority = AllowFree(dPriority);
        const char* assignedTo = "unassigned";
        if (sufficientFee && !sufficientPriority)
        {
            history[nBlocksTruncated].RecordFee(feeRate);
            assignedTo = "fee";
        }
        else if (sufficientPriority && !sufficientFee)
        {
            history[nBlocksTruncated].RecordPriority(dPriority);
            assignedTo = "priority";
        }
        else
        {
            // Neither or both fee and priority sufficient to get confirmed:
            // don't know why they got confirmed.
        }
        LogPrint("estimatefee", "Seen TX confirm: %s : %s fee/%g priority, took %d blocks\n",
                 assignedTo, feeRate.ToString(), dPriority, nBlocksAgo);
    }

public:
    CMinerPolicyEstimator(int nEntries) : nBestSeenHeight(0)
    {
        history.resize(nEntries);
    }

Gavin Andresen's avatar
Gavin Andresen committed
185
    void seenBlock(const std::vector<CTxMemPoolEntry>& entries, int nBlockHeight, const CFeeRate minRelayFee)
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
    {
        if (nBlockHeight <= nBestSeenHeight)
        {
            // Ignore side chains and re-orgs; assuming they are random
            // they don't affect the estimate.
            // And if an attacker can re-org the chain at will, then
            // you've got much bigger problems than "attacker can influence
            // transaction fees."
            return;
        }
        nBestSeenHeight = nBlockHeight;

        // Fill up the history buckets based on how long transactions took
        // to confirm.
        std::vector<std::vector<const CTxMemPoolEntry*> > entriesByConfirmations;
        entriesByConfirmations.resize(history.size());
        BOOST_FOREACH(const CTxMemPoolEntry& entry, entries)
        {
            // How many blocks did it take for miners to include this transaction?
            int delta = nBlockHeight - entry.GetHeight();
            if (delta <= 0)
            {
                // Re-org made us lose height, this should only happen if we happen
                // to re-org on a difficulty transition point: very rare!
                continue;
            }
            if ((delta-1) >= (int)history.size())
                delta = history.size(); // Last bucket is catch-all
214
            entriesByConfirmations.at(delta-1).push_back(&entry);
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
        }
        for (size_t i = 0; i < entriesByConfirmations.size(); i++)
        {
            std::vector<const CTxMemPoolEntry*> &e = entriesByConfirmations.at(i);
            // Insert at most 10 random entries per bucket, otherwise a single block
            // can dominate an estimate:
            if (e.size() > 10) {
                std::random_shuffle(e.begin(), e.end());
                e.resize(10);
            }
            BOOST_FOREACH(const CTxMemPoolEntry* entry, e)
            {
                // Fees are stored and reported as BTC-per-kb:
                CFeeRate feeRate(entry->GetFee(), entry->GetTxSize());
                double dPriority = entry->GetPriority(entry->GetHeight()); // Want priority when it went IN
Gavin Andresen's avatar
Gavin Andresen committed
230
                seenTxConfirm(feeRate, minRelayFee, dPriority, i);
231
232
            }
        }
233
234
235
236
237
238

        //After new samples are added, we have to clear the sorted lists,
        //so they'll be resorted the next time someone asks for an estimate
        sortedFeeSamples.clear();
        sortedPrioritySamples.clear();

239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
        for (size_t i = 0; i < history.size(); i++) {
            if (history[i].FeeSamples() + history[i].PrioritySamples() > 0)
                LogPrint("estimatefee", "estimates: for confirming within %d blocks based on %d/%d samples, fee=%s, prio=%g\n", 
                         i,
                         history[i].FeeSamples(), history[i].PrioritySamples(),
                         estimateFee(i+1).ToString(), estimatePriority(i+1));
        }
    }

    // Can return CFeeRate(0) if we don't have any data for that many blocks back. nBlocksToConfirm is 1 based.
    CFeeRate estimateFee(int nBlocksToConfirm)
    {
        nBlocksToConfirm--;

        if (nBlocksToConfirm < 0 || nBlocksToConfirm >= (int)history.size())
            return CFeeRate(0);

        if (sortedFeeSamples.size() == 0)
        {
            for (size_t i = 0; i < history.size(); i++)
                history.at(i).GetFeeSamples(sortedFeeSamples);
            std::sort(sortedFeeSamples.begin(), sortedFeeSamples.end(),
                      std::greater<CFeeRate>());
        }
Gavin Andresen's avatar
Gavin Andresen committed
263
264
265
266
267
        if (sortedFeeSamples.size() < 11)
        {
            // Eleven is Gavin's Favorite Number
            // ... but we also take a maximum of 10 samples per block so eleven means
            // we're getting samples from at least two different blocks
268
            return CFeeRate(0);
Gavin Andresen's avatar
Gavin Andresen committed
269
        }
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297

        int nBucketSize = history.at(nBlocksToConfirm).FeeSamples();

        // Estimates should not increase as number of confirmations goes up,
        // but the estimates are noisy because confirmations happen discretely
        // in blocks. To smooth out the estimates, use all samples in the history
        // and use the nth highest where n is (number of samples in previous bucket +
        // half the samples in nBlocksToConfirm bucket):
        size_t nPrevSize = 0;
        for (int i = 0; i < nBlocksToConfirm; i++)
            nPrevSize += history.at(i).FeeSamples();
        size_t index = min(nPrevSize + nBucketSize/2, sortedFeeSamples.size()-1);
        return sortedFeeSamples[index];
    }
    double estimatePriority(int nBlocksToConfirm)
    {
        nBlocksToConfirm--;

        if (nBlocksToConfirm < 0 || nBlocksToConfirm >= (int)history.size())
            return -1;

        if (sortedPrioritySamples.size() == 0)
        {
            for (size_t i = 0; i < history.size(); i++)
                history.at(i).GetPrioritySamples(sortedPrioritySamples);
            std::sort(sortedPrioritySamples.begin(), sortedPrioritySamples.end(),
                      std::greater<double>());
        }
Gavin Andresen's avatar
Gavin Andresen committed
298
        if (sortedPrioritySamples.size() < 11)
299
300
301
302
303
304
305
306
307
308
309
310
            return -1.0;

        int nBucketSize = history.at(nBlocksToConfirm).PrioritySamples();

        // Estimates should not increase as number of confirmations needed goes up,
        // but the estimates are noisy because confirmations happen discretely
        // in blocks. To smooth out the estimates, use all samples in the history
        // and use the nth highest where n is (number of samples in previous buckets +
        // half the samples in nBlocksToConfirm bucket).
        size_t nPrevSize = 0;
        for (int i = 0; i < nBlocksToConfirm; i++)
            nPrevSize += history.at(i).PrioritySamples();
311
        size_t index = min(nPrevSize + nBucketSize/2, sortedPrioritySamples.size()-1);
312
313
314
315
316
317
318
319
320
321
322
323
324
        return sortedPrioritySamples[index];
    }

    void Write(CAutoFile& fileout) const
    {
        fileout << nBestSeenHeight;
        fileout << history.size();
        BOOST_FOREACH(const CBlockAverage& entry, history)
        {
            entry.Write(fileout);
        }
    }

Gavin Andresen's avatar
Gavin Andresen committed
325
    void Read(CAutoFile& filein, const CFeeRate& minRelayFee)
326
    {
327
328
        int nFileBestSeenHeight;
        filein >> nFileBestSeenHeight;
329
330
        size_t numEntries;
        filein >> numEntries;
331
332
333
334
335
        if (numEntries <= 0 || numEntries > 10000)
            throw runtime_error("Corrupt estimates file.  Must have between 1 and 10k entires.");

        std::vector<CBlockAverage> fileHistory;
        
336
337
338
        for (size_t i = 0; i < numEntries; i++)
        {
            CBlockAverage entry;
Gavin Andresen's avatar
Gavin Andresen committed
339
            entry.Read(filein, minRelayFee);
340
            fileHistory.push_back(entry);
341
        }
342
343
344
345
346
347

        //Now that we've processed the entire fee estimate data file and not
        //thrown any errors, we can copy it to our history
        nBestSeenHeight = nFileBestSeenHeight;
        history = fileHistory;
        assert(history.size() > 0);
348
349
350
351
    }
};


352
353
354
CTxMemPool::CTxMemPool(const CFeeRate& _minRelayFee) :
    nTransactionsUpdated(0),
    minRelayFee(_minRelayFee)
355
356
357
358
359
{
    // Sanity checks off by default for performance, because otherwise
    // accepting transactions becomes O(N^2) where N is the number
    // of transactions in the pool
    fSanityCheck = false;
360
361
362
363
364
365
366
367
368
369
370
371

    // 25 blocks is a compromise between using a lot of disk/memory and
    // trying to give accurate estimates to people who might be willing
    // to wait a day or two to save a fraction of a penny in fees.
    // Confirmation times for very-low-fee transactions that take more
    // than an hour or three to confirm are highly variable.
    minerPolicyEstimator = new CMinerPolicyEstimator(25);
}

CTxMemPool::~CTxMemPool()
{
    delete minerPolicyEstimator;
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
}

void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins)
{
    LOCK(cs);

    std::map<COutPoint, CInPoint>::iterator it = mapNextTx.lower_bound(COutPoint(hashTx, 0));

    // iterate over all COutPoints in mapNextTx whose hash equals the provided hashTx
    while (it != mapNextTx.end() && it->first.hash == hashTx) {
        coins.Spend(it->first.n); // and remove those outputs from coins
        it++;
    }
}

unsigned int CTxMemPool::GetTransactionsUpdated() const
{
    LOCK(cs);
    return nTransactionsUpdated;
}

void CTxMemPool::AddTransactionsUpdated(unsigned int n)
{
    LOCK(cs);
    nTransactionsUpdated += n;
}


400
bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry)
401
402
403
404
405
406
{
    // Add to memory pool without checking anything.
    // Used by main.cpp AcceptToMemoryPool(), which DOES do
    // all the appropriate checks.
    LOCK(cs);
    {
407
408
        mapTx[hash] = entry;
        const CTransaction& tx = mapTx[hash].GetTx();
409
        for (unsigned int i = 0; i < tx.vin.size(); i++)
410
            mapNextTx[tx.vin[i].prevout] = CInPoint(&tx, i);
411
        nTransactionsUpdated++;
412
        totalTxSize += entry.GetTxSize();
413
414
415
416
417
    }
    return true;
}


Gavin Andresen's avatar
Gavin Andresen committed
418
void CTxMemPool::remove(const CTransaction &tx, std::list<CTransaction>& removed, bool fRecursive)
419
420
421
422
423
424
425
426
{
    // Remove transaction from memory pool
    {
        LOCK(cs);
        uint256 hash = tx.GetHash();
        if (fRecursive) {
            for (unsigned int i = 0; i < tx.vout.size(); i++) {
                std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(COutPoint(hash, i));
Gavin Andresen's avatar
Gavin Andresen committed
427
428
429
                if (it == mapNextTx.end())
                    continue;
                remove(*it->second.ptx, removed, true);
430
431
432
433
            }
        }
        if (mapTx.count(hash))
        {
Gavin Andresen's avatar
Gavin Andresen committed
434
            removed.push_front(tx);
435
436
            BOOST_FOREACH(const CTxIn& txin, tx.vin)
                mapNextTx.erase(txin.prevout);
437
438

            totalTxSize -= mapTx[hash].GetTxSize();
439
440
441
442
443
444
            mapTx.erase(hash);
            nTransactionsUpdated++;
        }
    }
}

Gavin Andresen's avatar
Gavin Andresen committed
445
void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed)
446
447
{
    // Remove transactions which depend on inputs of tx, recursively
448
    list<CTransaction> result;
449
450
451
452
453
454
    LOCK(cs);
    BOOST_FOREACH(const CTxIn &txin, tx.vin) {
        std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(txin.prevout);
        if (it != mapNextTx.end()) {
            const CTransaction &txConflict = *it->second.ptx;
            if (txConflict != tx)
Gavin Andresen's avatar
Gavin Andresen committed
455
456
457
            {
                remove(txConflict, removed, true);
            }
458
459
460
461
        }
    }
}

462
463
464
465
466
467
468
469
470
471
472
473
// Called when a block is connected. Removes from mempool and updates the miner fee estimator.
void CTxMemPool::removeForBlock(const std::vector<CTransaction>& vtx, unsigned int nBlockHeight,
                                std::list<CTransaction>& conflicts)
{
    LOCK(cs);
    std::vector<CTxMemPoolEntry> entries;
    BOOST_FOREACH(const CTransaction& tx, vtx)
    {
        uint256 hash = tx.GetHash();
        if (mapTx.count(hash))
            entries.push_back(mapTx[hash]);
    }
Gavin Andresen's avatar
Gavin Andresen committed
474
    minerPolicyEstimator->seenBlock(entries, nBlockHeight, minRelayFee);
475
476
477
478
479
    BOOST_FOREACH(const CTransaction& tx, vtx)
    {
        std::list<CTransaction> dummy;
        remove(tx, dummy, false);
        removeConflicts(tx, conflicts);
480
        ClearPrioritisation(tx.GetHash());
481
482
483
484
    }
}


485
486
487
488
489
void CTxMemPool::clear()
{
    LOCK(cs);
    mapTx.clear();
    mapNextTx.clear();
490
    totalTxSize = 0;
491
492
493
    ++nTransactionsUpdated;
}

494
void CTxMemPool::check(const CCoinsViewCache *pcoins) const
495
496
497
498
499
500
{
    if (!fSanityCheck)
        return;

    LogPrint("mempool", "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());

501
502
    uint64_t checkTotal = 0;

503
    LOCK(cs);
504
    for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
505
        unsigned int i = 0;
506
        checkTotal += it->second.GetTxSize();
507
508
        const CTransaction& tx = it->second.GetTx();
        BOOST_FOREACH(const CTxIn &txin, tx.vin) {
509
            // Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
510
            std::map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(txin.prevout.hash);
511
            if (it2 != mapTx.end()) {
512
513
                const CTransaction& tx2 = it2->second.GetTx();
                assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
514
            } else {
515
516
                const CCoins* coins = pcoins->AccessCoins(txin.prevout.hash);
                assert(coins && coins->IsAvailable(txin.prevout.n));
517
518
519
520
            }
            // Check whether its inputs are marked in mapNextTx.
            std::map<COutPoint, CInPoint>::const_iterator it3 = mapNextTx.find(txin.prevout);
            assert(it3 != mapNextTx.end());
521
            assert(it3->second.ptx == &tx);
522
523
524
525
526
527
            assert(it3->second.n == i);
            i++;
        }
    }
    for (std::map<COutPoint, CInPoint>::const_iterator it = mapNextTx.begin(); it != mapNextTx.end(); it++) {
        uint256 hash = it->second.ptx->GetHash();
528
529
        map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(hash);
        const CTransaction& tx = it2->second.GetTx();
530
        assert(it2 != mapTx.end());
531
532
        assert(&tx == it->second.ptx);
        assert(tx.vin.size() > it->second.n);
533
534
        assert(it->first == it->second.ptx->vin[it->second.n].prevout);
    }
535
536

    assert(totalTxSize == checkTotal);
537
538
}

539
void CTxMemPool::queryHashes(vector<uint256>& vtxid)
540
541
542
543
544
{
    vtxid.clear();

    LOCK(cs);
    vtxid.reserve(mapTx.size());
545
    for (map<uint256, CTxMemPoolEntry>::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi)
546
547
548
549
550
551
        vtxid.push_back((*mi).first);
}

bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const
{
    LOCK(cs);
552
    map<uint256, CTxMemPoolEntry>::const_iterator i = mapTx.find(hash);
553
    if (i == mapTx.end()) return false;
554
    result = i->second.GetTx();
555
556
    return true;
}
557

558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
CFeeRate CTxMemPool::estimateFee(int nBlocks) const
{
    LOCK(cs);
    return minerPolicyEstimator->estimateFee(nBlocks);
}
double CTxMemPool::estimatePriority(int nBlocks) const
{
    LOCK(cs);
    return minerPolicyEstimator->estimatePriority(nBlocks);
}

bool
CTxMemPool::WriteFeeEstimates(CAutoFile& fileout) const
{
    try {
        LOCK(cs);
        fileout << 99900; // version required to read: 0.9.99 or later
        fileout << CLIENT_VERSION; // version that wrote the file
        minerPolicyEstimator->Write(fileout);
    }
ENikS's avatar
ENikS committed
578
    catch (const std::exception &) {
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
        LogPrintf("CTxMemPool::WriteFeeEstimates() : unable to write policy estimator data (non-fatal)");
        return false;
    }
    return true;
}

bool
CTxMemPool::ReadFeeEstimates(CAutoFile& filein)
{
    try {
        int nVersionRequired, nVersionThatWrote;
        filein >> nVersionRequired >> nVersionThatWrote;
        if (nVersionRequired > CLIENT_VERSION)
            return error("CTxMemPool::ReadFeeEstimates() : up-version (%d) fee estimate file", nVersionRequired);

        LOCK(cs);
Gavin Andresen's avatar
Gavin Andresen committed
595
        minerPolicyEstimator->Read(filein, minRelayFee);
596
    }
ENikS's avatar
ENikS committed
597
    catch (const std::exception &) {
598
599
600
601
602
603
        LogPrintf("CTxMemPool::ReadFeeEstimates() : unable to read policy estimator data (non-fatal)");
        return false;
    }
    return true;
}

604
605
606
607
608
609
610
611
void CTxMemPool::PrioritiseTransaction(const uint256 hash, const string strHash, double dPriorityDelta, int64_t nFeeDelta)
{
    {
        LOCK(cs);
        std::pair<double, int64_t> &deltas = mapDeltas[hash];
        deltas.first += dPriorityDelta;
        deltas.second += nFeeDelta;
    }
612
    LogPrintf("PrioritiseTransaction: %s priority += %f, fee += %d\n", strHash, dPriorityDelta, nFeeDelta);
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
}

void CTxMemPool::ApplyDeltas(const uint256 hash, double &dPriorityDelta, int64_t &nFeeDelta)
{
    LOCK(cs);
    std::map<uint256, std::pair<double, int64_t> >::iterator pos = mapDeltas.find(hash);
    if (pos == mapDeltas.end())
        return;
    const std::pair<double, int64_t> &deltas = pos->second;
    dPriorityDelta += deltas.first;
    nFeeDelta += deltas.second;
}

void CTxMemPool::ClearPrioritisation(const uint256 hash)
{
    LOCK(cs);
    mapDeltas.erase(hash);
}

632

633
CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView *baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { }
634

635
bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) const {
636
637
638
    // If an entry in the mempool exists, always return that one, as it's guaranteed to never
    // conflict with the underlying cache, and it cannot have pruned entries (as it contains full)
    // transactions. First checking the underlying cache risks returning a pruned entry instead.
639
640
641
642
643
    CTransaction tx;
    if (mempool.lookup(txid, tx)) {
        coins = CCoins(tx, MEMPOOL_HEIGHT);
        return true;
    }
644
    return (base->GetCoins(txid, coins) && !coins.IsPruned());
645
646
}

647
bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) const {
648
649
    return mempool.exists(txid) || base->HaveCoins(txid);
}