]> Git Repo - VerusCoin.git/blob - src/txmempool.cpp
Merge pull request #3682
[VerusCoin.git] / src / txmempool.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2013 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #include "core.h"
7 #include "txmempool.h"
8
9 using namespace std;
10
11 CTxMemPoolEntry::CTxMemPoolEntry()
12 {
13     nHeight = MEMPOOL_HEIGHT;
14 }
15
16 CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, int64_t _nFee,
17                                  int64_t _nTime, double _dPriority,
18                                  unsigned int _nHeight):
19     tx(_tx), nFee(_nFee), nTime(_nTime), dPriority(_dPriority), nHeight(_nHeight)
20 {
21     nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
22 }
23
24 CTxMemPoolEntry::CTxMemPoolEntry(const CTxMemPoolEntry& other)
25 {
26     *this = other;
27 }
28
29 double
30 CTxMemPoolEntry::GetPriority(unsigned int currentHeight) const
31 {
32     int64_t nValueIn = tx.GetValueOut()+nFee;
33     double deltaPriority = ((double)(currentHeight-nHeight)*nValueIn)/nTxSize;
34     double dResult = dPriority + deltaPriority;
35     return dResult;
36 }
37
38 CTxMemPool::CTxMemPool()
39 {
40     // Sanity checks off by default for performance, because otherwise
41     // accepting transactions becomes O(N^2) where N is the number
42     // of transactions in the pool
43     fSanityCheck = false;
44 }
45
46 void CTxMemPool::pruneSpent(const uint256 &hashTx, CCoins &coins)
47 {
48     LOCK(cs);
49
50     std::map<COutPoint, CInPoint>::iterator it = mapNextTx.lower_bound(COutPoint(hashTx, 0));
51
52     // iterate over all COutPoints in mapNextTx whose hash equals the provided hashTx
53     while (it != mapNextTx.end() && it->first.hash == hashTx) {
54         coins.Spend(it->first.n); // and remove those outputs from coins
55         it++;
56     }
57 }
58
59 unsigned int CTxMemPool::GetTransactionsUpdated() const
60 {
61     LOCK(cs);
62     return nTransactionsUpdated;
63 }
64
65 void CTxMemPool::AddTransactionsUpdated(unsigned int n)
66 {
67     LOCK(cs);
68     nTransactionsUpdated += n;
69 }
70
71
72 bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry)
73 {
74     // Add to memory pool without checking anything.
75     // Used by main.cpp AcceptToMemoryPool(), which DOES do
76     // all the appropriate checks.
77     LOCK(cs);
78     {
79         mapTx[hash] = entry;
80         const CTransaction& tx = mapTx[hash].GetTx();
81         for (unsigned int i = 0; i < tx.vin.size(); i++)
82             mapNextTx[tx.vin[i].prevout] = CInPoint(&tx, i);
83         nTransactionsUpdated++;
84     }
85     return true;
86 }
87
88
89 void CTxMemPool::remove(const CTransaction &tx, std::list<CTransaction>& removed, bool fRecursive)
90 {
91     // Remove transaction from memory pool
92     {
93         LOCK(cs);
94         uint256 hash = tx.GetHash();
95         if (fRecursive) {
96             for (unsigned int i = 0; i < tx.vout.size(); i++) {
97                 std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(COutPoint(hash, i));
98                 if (it == mapNextTx.end())
99                     continue;
100                 remove(*it->second.ptx, removed, true);
101             }
102         }
103         if (mapTx.count(hash))
104         {
105             removed.push_front(tx);
106             BOOST_FOREACH(const CTxIn& txin, tx.vin)
107                 mapNextTx.erase(txin.prevout);
108             mapTx.erase(hash);
109             nTransactionsUpdated++;
110         }
111     }
112 }
113
114 void CTxMemPool::removeConflicts(const CTransaction &tx, std::list<CTransaction>& removed)
115 {
116     // Remove transactions which depend on inputs of tx, recursively
117     list<CTransaction> result;
118     LOCK(cs);
119     BOOST_FOREACH(const CTxIn &txin, tx.vin) {
120         std::map<COutPoint, CInPoint>::iterator it = mapNextTx.find(txin.prevout);
121         if (it != mapNextTx.end()) {
122             const CTransaction &txConflict = *it->second.ptx;
123             if (txConflict != tx)
124             {
125                 remove(txConflict, removed, true);
126             }
127         }
128     }
129 }
130
131 void CTxMemPool::clear()
132 {
133     LOCK(cs);
134     mapTx.clear();
135     mapNextTx.clear();
136     ++nTransactionsUpdated;
137 }
138
139 void CTxMemPool::check(CCoinsViewCache *pcoins) const
140 {
141     if (!fSanityCheck)
142         return;
143
144     LogPrint("mempool", "Checking mempool with %u transactions and %u inputs\n", (unsigned int)mapTx.size(), (unsigned int)mapNextTx.size());
145
146     LOCK(cs);
147     for (std::map<uint256, CTxMemPoolEntry>::const_iterator it = mapTx.begin(); it != mapTx.end(); it++) {
148         unsigned int i = 0;
149         const CTransaction& tx = it->second.GetTx();
150         BOOST_FOREACH(const CTxIn &txin, tx.vin) {
151             // Check that every mempool transaction's inputs refer to available coins, or other mempool tx's.
152             std::map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(txin.prevout.hash);
153             if (it2 != mapTx.end()) {
154                 const CTransaction& tx2 = it2->second.GetTx();
155                 assert(tx2.vout.size() > txin.prevout.n && !tx2.vout[txin.prevout.n].IsNull());
156             } else {
157                 CCoins &coins = pcoins->GetCoins(txin.prevout.hash);
158                 assert(coins.IsAvailable(txin.prevout.n));
159             }
160             // Check whether its inputs are marked in mapNextTx.
161             std::map<COutPoint, CInPoint>::const_iterator it3 = mapNextTx.find(txin.prevout);
162             assert(it3 != mapNextTx.end());
163             assert(it3->second.ptx == &tx);
164             assert(it3->second.n == i);
165             i++;
166         }
167     }
168     for (std::map<COutPoint, CInPoint>::const_iterator it = mapNextTx.begin(); it != mapNextTx.end(); it++) {
169         uint256 hash = it->second.ptx->GetHash();
170         map<uint256, CTxMemPoolEntry>::const_iterator it2 = mapTx.find(hash);
171         const CTransaction& tx = it2->second.GetTx();
172         assert(it2 != mapTx.end());
173         assert(&tx == it->second.ptx);
174         assert(tx.vin.size() > it->second.n);
175         assert(it->first == it->second.ptx->vin[it->second.n].prevout);
176     }
177 }
178
179 void CTxMemPool::queryHashes(vector<uint256>& vtxid)
180 {
181     vtxid.clear();
182
183     LOCK(cs);
184     vtxid.reserve(mapTx.size());
185     for (map<uint256, CTxMemPoolEntry>::iterator mi = mapTx.begin(); mi != mapTx.end(); ++mi)
186         vtxid.push_back((*mi).first);
187 }
188
189 bool CTxMemPool::lookup(uint256 hash, CTransaction& result) const
190 {
191     LOCK(cs);
192     map<uint256, CTxMemPoolEntry>::const_iterator i = mapTx.find(hash);
193     if (i == mapTx.end()) return false;
194     result = i->second.GetTx();
195     return true;
196 }
197
198 CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView &baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { }
199
200 bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) {
201     if (base->GetCoins(txid, coins))
202         return true;
203     CTransaction tx;
204     if (mempool.lookup(txid, tx)) {
205         coins = CCoins(tx, MEMPOOL_HEIGHT);
206         return true;
207     }
208     return false;
209 }
210
211 bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) {
212     return mempool.exists(txid) || base->HaveCoins(txid);
213 }
214
This page took 0.036504 seconds and 4 git commands to generate.