]> Git Repo - VerusCoin.git/blobdiff - src/txmempool.cpp
remove fields of ser_streamplaceholder
[VerusCoin.git] / src / txmempool.cpp
index a852de5da885092a674a6fea5dbbf557bb892202..238d5bab16766706dc505bc3ca5fccb92806a1f2 100644 (file)
@@ -5,12 +5,14 @@
 
 #include "core.h"
 #include "txmempool.h"
+#include "util.h"
 
 #include <boost/circular_buffer.hpp>
 
 using namespace std;
 
-CTxMemPoolEntry::CTxMemPoolEntry()
+CTxMemPoolEntry::CTxMemPoolEntry():
+    nFee(0), nTxSize(0), nTime(0), dPriority(0.0)
 {
     nHeight = MEMPOOL_HEIGHT;
 }
@@ -206,7 +208,7 @@ public:
             }
             if ((delta-1) >= (int)history.size())
                 delta = history.size(); // Last bucket is catch-all
-            entriesByConfirmations[delta-1].push_back(&entry);
+            entriesByConfirmations.at(delta-1).push_back(&entry);
         }
         for (size_t i = 0; i < entriesByConfirmations.size(); i++)
         {
@@ -225,6 +227,12 @@ public:
                 seenTxConfirm(feeRate, minRelayFee, dPriority, i);
             }
         }
+
+        //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();
+
         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", 
@@ -232,8 +240,6 @@ public:
                          history[i].FeeSamples(), history[i].PrioritySamples(),
                          estimateFee(i+1).ToString(), estimatePriority(i+1));
         }
-        sortedFeeSamples.clear();
-        sortedPrioritySamples.clear();
     }
 
     // Can return CFeeRate(0) if we don't have any data for that many blocks back. nBlocksToConfirm is 1 based.
@@ -299,7 +305,7 @@ public:
         size_t nPrevSize = 0;
         for (int i = 0; i < nBlocksToConfirm; i++)
             nPrevSize += history.at(i).PrioritySamples();
-        size_t index = min(nPrevSize + nBucketSize/2, sortedFeeSamples.size()-1);
+        size_t index = min(nPrevSize + nBucketSize/2, sortedPrioritySamples.size()-1);
         return sortedPrioritySamples[index];
     }
 
@@ -315,21 +321,34 @@ public:
 
     void Read(CAutoFile& filein, const CFeeRate& minRelayFee)
     {
-        filein >> nBestSeenHeight;
+        int nFileBestSeenHeight;
+        filein >> nFileBestSeenHeight;
         size_t numEntries;
         filein >> numEntries;
-        history.clear();
+        if (numEntries <= 0 || numEntries > 10000)
+            throw runtime_error("Corrupt estimates file.  Must have between 1 and 10k entires.");
+
+        std::vector<CBlockAverage> fileHistory;
+        
         for (size_t i = 0; i < numEntries; i++)
         {
             CBlockAverage entry;
             entry.Read(filein, minRelayFee);
-            history.push_back(entry);
+            fileHistory.push_back(entry);
         }
+
+        //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);
     }
 };
 
 
-CTxMemPool::CTxMemPool(const CFeeRate& _minRelayFee) : minRelayFee(_minRelayFee)
+CTxMemPool::CTxMemPool(const CFeeRate& _minRelayFee) :
+    nTransactionsUpdated(0),
+    minRelayFee(_minRelayFee)
 {
     // Sanity checks off by default for performance, because otherwise
     // accepting transactions becomes O(N^2) where N is the number
@@ -387,6 +406,7 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry)
         for (unsigned int i = 0; i < tx.vin.size(); i++)
             mapNextTx[tx.vin[i].prevout] = CInPoint(&tx, i);
         nTransactionsUpdated++;
+        totalTxSize += entry.GetTxSize();
     }
     return true;
 }
@@ -411,6 +431,8 @@ void CTxMemPool::remove(const CTransaction &tx, std::list<CTransaction>& removed
             removed.push_front(tx);
             BOOST_FOREACH(const CTxIn& txin, tx.vin)
                 mapNextTx.erase(txin.prevout);
+
+            totalTxSize -= mapTx[hash].GetTxSize();
             mapTx.erase(hash);
             nTransactionsUpdated++;
         }
@@ -420,6 +442,7 @@ void CTxMemPool::remove(const CTransaction &tx, std::list<CTransaction>& removed
 void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed)
 {
     // Remove transactions which depend on inputs of tx, recursively
+    list<CTransaction> result;
     LOCK(cs);
     BOOST_FOREACH(const CTxIn &txin, tx.vin) {
         std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(txin.prevout);
@@ -461,19 +484,23 @@ void CTxMemPool::clear()
     LOCK(cs);
     mapTx.clear();
     mapNextTx.clear();
+    totalTxSize = 0;
     ++nTransactionsUpdated;
 }
 
-void CTxMemPool::check(CCoinsViewCache *pcoins) const
+void CTxMemPool::check(const CCoinsViewCache *pcoins) const
 {
     if (!fSanityCheck)
         return;
 
     LogPrint("mempool", "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
 
+    uint64_t checkTotal = 0;
+
     LOCK(cs);
     for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
         unsigned int i = 0;
+        checkTotal += it->second.GetTxSize();
         const CTransaction& tx = it->second.GetTx();
         BOOST_FOREACH(const CTxIn &txin, tx.vin) {
             // Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
@@ -482,7 +509,7 @@ void CTxMemPool::check(CCoinsViewCache *pcoins) const
                 const CTransaction& tx2 = it2->second.GetTx();
                 assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
             } else {
-                CCoins &coins = pcoins->GetCoins(txin.prevout.hash);
+                const CCoins &coins = pcoins->GetCoins(txin.prevout.hash);
                 assert(coins.IsAvailable(txin.prevout.n));
             }
             // Check whether its inputs are marked in mapNextTx.
@@ -502,6 +529,8 @@ void CTxMemPool::check(CCoinsViewCache *pcoins) const
         assert(tx.vin.size() > it->second.n);
         assert(it->first == it->second.ptx->vin[it->second.n].prevout);
     }
+
+    assert(totalTxSize == checkTotal);
 }
 
 void CTxMemPool::queryHashes(vector<uint256>& vtxid)
@@ -600,18 +629,19 @@ void CTxMemPool::ClearPrioritisation(const uint256 hash)
 
 CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView &baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { }
 
-bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) {
-    if (base->GetCoins(txid, coins))
-        return true;
+bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) const {
+    // 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.
     CTransaction tx;
     if (mempool.lookup(txid, tx)) {
         coins = CCoins(tx, MEMPOOL_HEIGHT);
         return true;
     }
-    return false;
+    return (base->GetCoins(txid, coins) && !coins.IsPruned());
 }
 
-bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) {
+bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) const {
     return mempool.exists(txid) || base->HaveCoins(txid);
 }
 
This page took 0.029336 seconds and 4 git commands to generate.