Dash Core  0.12.2.1
P2P Digital Currency
coins.cpp
Go to the documentation of this file.
1 // Copyright (c) 2012-2015 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 "memusage.h"
8 #include "random.h"
9 
10 #include <assert.h>
11 
17 void CCoins::CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const {
18  unsigned int nLastUsedByte = 0;
19  for (unsigned int b = 0; 2+b*8 < vout.size(); b++) {
20  bool fZero = true;
21  for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++) {
22  if (!vout[2+b*8+i].IsNull()) {
23  fZero = false;
24  continue;
25  }
26  }
27  if (!fZero) {
28  nLastUsedByte = b + 1;
29  nNonzeroBytes++;
30  }
31  }
32  nBytes += nLastUsedByte;
33 }
34 
35 bool CCoins::Spend(uint32_t nPos)
36 {
37  if (nPos >= vout.size() || vout[nPos].IsNull())
38  return false;
39  vout[nPos].SetNull();
40  Cleanup();
41  return true;
42 }
43 
44 bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; }
45 bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; }
47 bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; }
48 bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; }
49 
50 
52 bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); }
53 bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); }
55 void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
56 bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
57 bool CCoinsViewBacked::GetStats(CCoinsStats &stats) const { return base->GetStats(stats); }
58 
60 
61 CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), hasModifier(false), cachedCoinsUsage(0) { }
62 
64 {
65  assert(!hasModifier);
66 }
67 
70 }
71 
72 CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256 &txid) const {
73  CCoinsMap::iterator it = cacheCoins.find(txid);
74  if (it != cacheCoins.end())
75  return it;
76  CCoins tmp;
77  if (!base->GetCoins(txid, tmp))
78  return cacheCoins.end();
79  CCoinsMap::iterator ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry())).first;
80  tmp.swap(ret->second.coins);
81  if (ret->second.coins.IsPruned()) {
82  // The parent only has an empty entry for this txid; we can consider our
83  // version as fresh.
84  ret->second.flags = CCoinsCacheEntry::FRESH;
85  }
86  cachedCoinsUsage += ret->second.coins.DynamicMemoryUsage();
87  return ret;
88 }
89 
90 bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) const {
91  CCoinsMap::const_iterator it = FetchCoins(txid);
92  if (it != cacheCoins.end()) {
93  coins = it->second.coins;
94  return true;
95  }
96  return false;
97 }
98 
100  assert(!hasModifier);
101  std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry()));
102  size_t cachedCoinUsage = 0;
103  if (ret.second) {
104  if (!base->GetCoins(txid, ret.first->second.coins)) {
105  // The parent view does not have this entry; mark it as fresh.
106  ret.first->second.coins.Clear();
107  ret.first->second.flags = CCoinsCacheEntry::FRESH;
108  } else if (ret.first->second.coins.IsPruned()) {
109  // The parent view only has a pruned entry for this; mark it as fresh.
110  ret.first->second.flags = CCoinsCacheEntry::FRESH;
111  }
112  } else {
113  cachedCoinUsage = ret.first->second.coins.DynamicMemoryUsage();
114  }
115  // Assume that whenever ModifyCoins is called, the entry will be modified.
116  ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
117  return CCoinsModifier(*this, ret.first, cachedCoinUsage);
118 }
119 
121  assert(!hasModifier);
122  std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry()));
123  ret.first->second.coins.Clear();
124  ret.first->second.flags = CCoinsCacheEntry::FRESH;
125  ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
126  return CCoinsModifier(*this, ret.first, 0);
127 }
128 
129 const CCoins* CCoinsViewCache::AccessCoins(const uint256 &txid) const {
130  CCoinsMap::const_iterator it = FetchCoins(txid);
131  if (it == cacheCoins.end()) {
132  return NULL;
133  } else {
134  return &it->second.coins;
135  }
136 }
137 
138 bool CCoinsViewCache::HaveCoins(const uint256 &txid) const {
139  CCoinsMap::const_iterator it = FetchCoins(txid);
140  // We're using vtx.empty() instead of IsPruned here for performance reasons,
141  // as we only care about the case where a transaction was replaced entirely
142  // in a reorganization (which wipes vout entirely, as opposed to spending
143  // which just cleans individual outputs).
144  return (it != cacheCoins.end() && !it->second.coins.vout.empty());
145 }
146 
148  CCoinsMap::const_iterator it = cacheCoins.find(txid);
149  return it != cacheCoins.end();
150 }
151 
153  if (hashBlock.IsNull())
155  return hashBlock;
156 }
157 
158 void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
159  hashBlock = hashBlockIn;
160 }
161 
162 bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn) {
163  assert(!hasModifier);
164  for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
165  if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
166  CCoinsMap::iterator itUs = cacheCoins.find(it->first);
167  if (itUs == cacheCoins.end()) {
168  // The parent cache does not have an entry, while the child does
169  // We can ignore it if it's both FRESH and pruned in the child
170  if (!(it->second.flags & CCoinsCacheEntry::FRESH && it->second.coins.IsPruned())) {
171  // Otherwise we will need to create it in the parent
172  // and move the data up and mark it as dirty
173  CCoinsCacheEntry& entry = cacheCoins[it->first];
174  entry.coins.swap(it->second.coins);
177  // We can mark it FRESH in the parent if it was FRESH in the child
178  // Otherwise it might have just been flushed from the parent's cache
179  // and already exist in the grandparent
180  if (it->second.flags & CCoinsCacheEntry::FRESH)
182  }
183  } else {
184  // Found the entry in the parent cache
185  if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
186  // The grandparent does not have an entry, and the child is
187  // modified and being pruned. This means we can just delete
188  // it from the parent.
189  cachedCoinsUsage -= itUs->second.coins.DynamicMemoryUsage();
190  cacheCoins.erase(itUs);
191  } else {
192  // A normal modification.
193  cachedCoinsUsage -= itUs->second.coins.DynamicMemoryUsage();
194  itUs->second.coins.swap(it->second.coins);
195  cachedCoinsUsage += itUs->second.coins.DynamicMemoryUsage();
196  itUs->second.flags |= CCoinsCacheEntry::DIRTY;
197  }
198  }
199  }
200  CCoinsMap::iterator itOld = it++;
201  mapCoins.erase(itOld);
202  }
203  hashBlock = hashBlockIn;
204  return true;
205 }
206 
208  bool fOk = base->BatchWrite(cacheCoins, hashBlock);
209  cacheCoins.clear();
210  cachedCoinsUsage = 0;
211  return fOk;
212 }
213 
215 {
216  CCoinsMap::iterator it = cacheCoins.find(hash);
217  if (it != cacheCoins.end() && it->second.flags == 0) {
218  cachedCoinsUsage -= it->second.coins.DynamicMemoryUsage();
219  cacheCoins.erase(it);
220  }
221 }
222 
223 unsigned int CCoinsViewCache::GetCacheSize() const {
224  return cacheCoins.size();
225 }
226 
227 const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const
228 {
229  const CCoins* coins = AccessCoins(input.prevout.hash);
230  assert(coins && coins->IsAvailable(input.prevout.n));
231  return coins->vout[input.prevout.n];
232 }
233 
235 {
236  if (tx.IsCoinBase())
237  return 0;
238 
239  CAmount nResult = 0;
240  for (unsigned int i = 0; i < tx.vin.size(); i++)
241  nResult += GetOutputFor(tx.vin[i]).nValue;
242 
243  return nResult;
244 }
245 
247 {
248  if (!tx.IsCoinBase()) {
249  for (unsigned int i = 0; i < tx.vin.size(); i++) {
250  const COutPoint &prevout = tx.vin[i].prevout;
251  const CCoins* coins = AccessCoins(prevout.hash);
252  if (!coins || !coins->IsAvailable(prevout.n)) {
253  return false;
254  }
255  }
256  }
257  return true;
258 }
259 
260 double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight, CAmount &inChainInputValue) const
261 {
262  inChainInputValue = 0;
263  if (tx.IsCoinBase())
264  return 0.0;
265  double dResult = 0.0;
266  BOOST_FOREACH(const CTxIn& txin, tx.vin)
267  {
268  const CCoins* coins = AccessCoins(txin.prevout.hash);
269  assert(coins);
270  if (!coins->IsAvailable(txin.prevout.n)) continue;
271  if (coins->nHeight <= nHeight) {
272  dResult += coins->vout[txin.prevout.n].nValue * (nHeight-coins->nHeight);
273  inChainInputValue += coins->vout[txin.prevout.n].nValue;
274  }
275  }
276  return tx.ComputePriority(dResult);
277 }
278 
279 CCoinsModifier::CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_, size_t usage) : cache(cache_), it(it_), cachedCoinUsage(usage) {
280  assert(!cache.hasModifier);
281  cache.hasModifier = true;
282 }
283 
285 {
286  assert(cache.hasModifier);
287  cache.hasModifier = false;
288  it->second.coins.Cleanup();
289  cache.cachedCoinsUsage -= cachedCoinUsage; // Subtract the old usage
290  if ((it->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
291  cache.cacheCoins.erase(it);
292  } else {
293  // If the coin still exists after the modification, add the new usage
294  cache.cachedCoinsUsage += it->second.coins.DynamicMemoryUsage();
295  }
296 }
string salt
Definition: rpcuser.py:25
uint32_t n
Definition: transaction.h:19
friend class CCoinsModifier
Definition: coins.h:481
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock)
Definition: coins.cpp:56
uint256 GetRandHash()
Definition: random.cpp:114
bool GetCoins(const uint256 &txid, CCoins &coins) const
Retrieve the CCoins (unspent transaction outputs) for a given txid.
Definition: coins.cpp:90
Definition: coins.h:73
bool GetStats(CCoinsStats &stats) const
Calculate statistics about the unspent transaction output set.
Definition: coins.cpp:57
CCoinsView * base
Definition: coins.h:344
size_t DynamicMemoryUsage() const
Calculate the size of the cache (in bytes)
Definition: coins.cpp:68
void swap(CCoins &to)
Definition: coins.h:128
static size_t DynamicUsage(const int8_t &v)
Definition: memusage.h:25
double ComputePriority(double dPriorityInputs, unsigned int nTxSize=0) const
struct event_base * base
Definition: torcontrol.cpp:659
CCoinsMap cacheCoins
Definition: coins.h:392
CCoinsModifier(CCoinsViewCache &cache_, CCoinsMap::iterator it_, size_t usage)
Definition: coins.cpp:279
bool IsAvailable(unsigned int nPos) const
check whether a particular output is still available
Definition: coins.h:245
CAmount nValue
Definition: transaction.h:136
boost::unordered_map< uint256, CCoinsCacheEntry, CCoinsKeyHasher > CCoinsMap
Definition: coins.h:298
bool HaveCoins(const uint256 &txid) const
Definition: coins.cpp:138
const CTxOut & GetOutputFor(const CTxIn &input) const
Definition: coins.cpp:227
virtual uint256 GetBestBlock() const
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: coins.cpp:46
CCoinsMap::iterator FetchCoins(const uint256 &txid)
uint256 hashBlock
Definition: coins.h:391
bool IsNull() const
Definition: uint256.h:33
void Cleanup()
remove spent outputs at the end of vout
Definition: coins.h:113
CCoins coins
Definition: coins.h:287
size_t DynamicMemoryUsage() const
Definition: coins.h:258
virtual bool GetCoins(const uint256 &txid, CCoins &coins) const
Retrieve the CCoins (unspent transaction outputs) for a given txid.
Definition: coins.cpp:44
virtual bool GetStats(CCoinsStats &stats) const
Calculate statistics about the unspent transaction output set.
Definition: coins.cpp:48
int64_t CAmount
Definition: amount.h:14
std::vector< CTxOut > vout
unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are d...
Definition: coins.h:80
CCoinsMap::iterator it
Definition: coins.h:368
CCoinsViewCache & cache
Definition: coins.h:367
COutPoint prevout
Definition: transaction.h:61
bool Spend(uint32_t nPos)
mark a vout spent
Definition: coins.cpp:35
unsigned char flags
Definition: coins.h:288
CCoinsViewCache(CCoinsView *baseIn)
Definition: coins.cpp:61
void SetBackend(CCoinsView &viewIn)
Definition: coins.cpp:55
~CCoinsViewCache()
Definition: coins.cpp:63
bool HaveInputs(const CTransaction &tx) const
Check whether all prevouts of the transaction are present in the UTXO set represented by this view...
Definition: coins.cpp:246
virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock)
Definition: coins.cpp:47
virtual bool HaveCoins(const uint256 &txid) const
Definition: coins.cpp:45
void SetBestBlock(const uint256 &hashBlock)
Definition: coins.cpp:158
CCoinsModifier ModifyCoins(const uint256 &txid)
Definition: coins.cpp:99
size_t cachedCoinUsage
Definition: coins.h:369
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock)
Definition: coins.cpp:162
uint256 GetBestBlock() const
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: coins.cpp:54
void Uncache(const uint256 &txid)
Definition: coins.cpp:214
const std::vector< CTxIn > vin
Definition: transaction.h:233
size_t cachedCoinsUsage
Definition: coins.h:395
CCoinsViewBacked(CCoinsView *viewIn)
Definition: coins.cpp:51
bool Flush()
Definition: coins.cpp:207
bool HaveCoinsInCache(const uint256 &txid) const
Definition: coins.cpp:147
double GetPriority(const CTransaction &tx, int nHeight, CAmount &inChainInputValue) const
Definition: coins.cpp:260
bool IsCoinBase() const
Definition: transaction.h:284
unsigned int GetCacheSize() const
Calculate the size of the cache (in number of transactions)
Definition: coins.cpp:223
bool HaveCoins(const uint256 &txid) const
Definition: coins.cpp:53
uint256 GetBestBlock() const
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: coins.cpp:152
void CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const
Definition: coins.cpp:17
bool hasModifier
Definition: coins.h:384
CCoinsModifier ModifyNewCoins(const uint256 &txid)
Definition: coins.cpp:120
uint256 hash
Definition: transaction.h:18
bool GetCoins(const uint256 &txid, CCoins &coins) const
Retrieve the CCoins (unspent transaction outputs) for a given txid.
Definition: coins.cpp:52
CAmount GetValueIn(const CTransaction &tx) const
Definition: coins.cpp:234
int nHeight
at which height this transaction was included in the active block chain
Definition: coins.h:83
const CCoins * AccessCoins(const uint256 &txid) const
Definition: coins.cpp:129