]> Git Repo - VerusCoin.git/blob - src/coins.cpp
Merge #5548: [REST] add /rest/chaininfos
[VerusCoin.git] / src / coins.cpp
1 // Copyright (c) 2012-2014 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5 #include "coins.h"
6
7 #include "random.h"
8
9 #include <assert.h>
10
11 /**
12  * calculate number of bytes for the bitmask, and its number of non-zero bytes
13  * each bit in the bitmask represents the availability of one output, but the
14  * availabilities of the first two outputs are encoded separately
15  */
16 void CCoins::CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const {
17     unsigned int nLastUsedByte = 0;
18     for (unsigned int b = 0; 2+b*8 < vout.size(); b++) {
19         bool fZero = true;
20         for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++) {
21             if (!vout[2+b*8+i].IsNull()) {
22                 fZero = false;
23                 continue;
24             }
25         }
26         if (!fZero) {
27             nLastUsedByte = b + 1;
28             nNonzeroBytes++;
29         }
30     }
31     nBytes += nLastUsedByte;
32 }
33
34 bool CCoins::Spend(uint32_t nPos) 
35 {
36     if (nPos >= vout.size() || vout[nPos].IsNull())
37         return false;
38     vout[nPos].SetNull();
39     Cleanup();
40     return true;
41 }
42
43 bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; }
44 bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; }
45 uint256 CCoinsView::GetBestBlock() const { return uint256(); }
46 bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; }
47 bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; }
48
49
50 CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { }
51 bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); }
52 bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); }
53 uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
54 void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
55 bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
56 bool CCoinsViewBacked::GetStats(CCoinsStats &stats) const { return base->GetStats(stats); }
57
58 CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {}
59
60 CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), hasModifier(false) { }
61
62 CCoinsViewCache::~CCoinsViewCache()
63 {
64     assert(!hasModifier);
65 }
66
67 CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256 &txid) const {
68     CCoinsMap::iterator it = cacheCoins.find(txid);
69     if (it != cacheCoins.end())
70         return it;
71     CCoins tmp;
72     if (!base->GetCoins(txid, tmp))
73         return cacheCoins.end();
74     CCoinsMap::iterator ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry())).first;
75     tmp.swap(ret->second.coins);
76     if (ret->second.coins.IsPruned()) {
77         // The parent only has an empty entry for this txid; we can consider our
78         // version as fresh.
79         ret->second.flags = CCoinsCacheEntry::FRESH;
80     }
81     return ret;
82 }
83
84 bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) const {
85     CCoinsMap::const_iterator it = FetchCoins(txid);
86     if (it != cacheCoins.end()) {
87         coins = it->second.coins;
88         return true;
89     }
90     return false;
91 }
92
93 CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256 &txid) {
94     assert(!hasModifier);
95     std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry()));
96     if (ret.second) {
97         if (!base->GetCoins(txid, ret.first->second.coins)) {
98             // The parent view does not have this entry; mark it as fresh.
99             ret.first->second.coins.Clear();
100             ret.first->second.flags = CCoinsCacheEntry::FRESH;
101         } else if (ret.first->second.coins.IsPruned()) {
102             // The parent view only has a pruned entry for this; mark it as fresh.
103             ret.first->second.flags = CCoinsCacheEntry::FRESH;
104         }
105     }
106     // Assume that whenever ModifyCoins is called, the entry will be modified.
107     ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
108     return CCoinsModifier(*this, ret.first);
109 }
110
111 const CCoins* CCoinsViewCache::AccessCoins(const uint256 &txid) const {
112     CCoinsMap::const_iterator it = FetchCoins(txid);
113     if (it == cacheCoins.end()) {
114         return NULL;
115     } else {
116         return &it->second.coins;
117     }
118 }
119
120 bool CCoinsViewCache::HaveCoins(const uint256 &txid) const {
121     CCoinsMap::const_iterator it = FetchCoins(txid);
122     // We're using vtx.empty() instead of IsPruned here for performance reasons,
123     // as we only care about the case where a transaction was replaced entirely
124     // in a reorganization (which wipes vout entirely, as opposed to spending
125     // which just cleans individual outputs).
126     return (it != cacheCoins.end() && !it->second.coins.vout.empty());
127 }
128
129 uint256 CCoinsViewCache::GetBestBlock() const {
130     if (hashBlock.IsNull())
131         hashBlock = base->GetBestBlock();
132     return hashBlock;
133 }
134
135 void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
136     hashBlock = hashBlockIn;
137 }
138
139 bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn) {
140     assert(!hasModifier);
141     for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
142         if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
143             CCoinsMap::iterator itUs = cacheCoins.find(it->first);
144             if (itUs == cacheCoins.end()) {
145                 if (!it->second.coins.IsPruned()) {
146                     // The parent cache does not have an entry, while the child
147                     // cache does have (a non-pruned) one. Move the data up, and
148                     // mark it as fresh (if the grandparent did have it, we
149                     // would have pulled it in at first GetCoins).
150                     assert(it->second.flags & CCoinsCacheEntry::FRESH);
151                     CCoinsCacheEntry& entry = cacheCoins[it->first];
152                     entry.coins.swap(it->second.coins);
153                     entry.flags = CCoinsCacheEntry::DIRTY | CCoinsCacheEntry::FRESH;
154                 }
155             } else {
156                 if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
157                     // The grandparent does not have an entry, and the child is
158                     // modified and being pruned. This means we can just delete
159                     // it from the parent.
160                     cacheCoins.erase(itUs);
161                 } else {
162                     // A normal modification.
163                     itUs->second.coins.swap(it->second.coins);
164                     itUs->second.flags |= CCoinsCacheEntry::DIRTY;
165                 }
166             }
167         }
168         CCoinsMap::iterator itOld = it++;
169         mapCoins.erase(itOld);
170     }
171     hashBlock = hashBlockIn;
172     return true;
173 }
174
175 bool CCoinsViewCache::Flush() {
176     bool fOk = base->BatchWrite(cacheCoins, hashBlock);
177     cacheCoins.clear();
178     return fOk;
179 }
180
181 unsigned int CCoinsViewCache::GetCacheSize() const {
182     return cacheCoins.size();
183 }
184
185 const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const
186 {
187     const CCoins* coins = AccessCoins(input.prevout.hash);
188     assert(coins && coins->IsAvailable(input.prevout.n));
189     return coins->vout[input.prevout.n];
190 }
191
192 CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const
193 {
194     if (tx.IsCoinBase())
195         return 0;
196
197     CAmount nResult = 0;
198     for (unsigned int i = 0; i < tx.vin.size(); i++)
199         nResult += GetOutputFor(tx.vin[i]).nValue;
200
201     return nResult;
202 }
203
204 bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
205 {
206     if (!tx.IsCoinBase()) {
207         for (unsigned int i = 0; i < tx.vin.size(); i++) {
208             const COutPoint &prevout = tx.vin[i].prevout;
209             const CCoins* coins = AccessCoins(prevout.hash);
210             if (!coins || !coins->IsAvailable(prevout.n)) {
211                 return false;
212             }
213         }
214     }
215     return true;
216 }
217
218 double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const
219 {
220     if (tx.IsCoinBase())
221         return 0.0;
222     double dResult = 0.0;
223     BOOST_FOREACH(const CTxIn& txin, tx.vin)
224     {
225         const CCoins* coins = AccessCoins(txin.prevout.hash);
226         assert(coins);
227         if (!coins->IsAvailable(txin.prevout.n)) continue;
228         if (coins->nHeight < nHeight) {
229             dResult += coins->vout[txin.prevout.n].nValue * (nHeight-coins->nHeight);
230         }
231     }
232     return tx.ComputePriority(dResult);
233 }
234
235 CCoinsModifier::CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_) : cache(cache_), it(it_) {
236     assert(!cache.hasModifier);
237     cache.hasModifier = true;
238 }
239
240 CCoinsModifier::~CCoinsModifier()
241 {
242     assert(cache.hasModifier);
243     cache.hasModifier = false;
244     it->second.coins.Cleanup();
245     if ((it->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
246         cache.cacheCoins.erase(it);
247     }
248 }
This page took 0.038393 seconds and 4 git commands to generate.