PRCYCoin  2.0.0.7rc1
P2P Digital Currency
coins.cpp
Go to the documentation of this file.
1 // Copyright (c) 2012-2014 The Bitcoin developers
2 // Copyright (c) 2015-2018 The PIVX developers
3 // Copyright (c) 2018-2020 The DAPS Project developers
4 // Distributed under the MIT software license, see the accompanying
5 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 
7 #include "coins.h"
8 
9 #include "memusage.h"
10 #include "random.h"
11 
12 #include <assert.h>
13 
19 void CCoins::CalcMaskSize(unsigned int& nBytes, unsigned int& nNonzeroBytes) const
20 {
21  unsigned int nLastUsedByte = 0;
22  for (unsigned int b = 0; 2 + b * 8 < vout.size(); b++) {
23  bool fZero = true;
24  for (unsigned int i = 0; i < 8 && 2 + b * 8 + i < vout.size(); i++) {
25  if (!vout[2 + b * 8 + i].IsNull()) {
26  fZero = false;
27  continue;
28  }
29  }
30  if (!fZero) {
31  nLastUsedByte = b + 1;
32  nNonzeroBytes++;
33  }
34  }
35  nBytes += nLastUsedByte;
36 }
37 
38 bool CCoins::Spend(const COutPoint& out, CTxInUndo& undo)
39 {
40  if (out.n >= vout.size()) {
41  return false;
42  }
43  if (vout[out.n].IsNull()) {
44  return false;
45  }
46  undo = CTxInUndo(vout[out.n]);
47  vout[out.n].SetNull();
48  Cleanup();
49  if (vout.size() == 0) {
50  undo.nHeight = nHeight;
51  undo.fCoinBase = fCoinBase;
52  undo.fCoinStake = fCoinStake;
53  undo.nVersion = this->nVersion;
54  }
55  return true;
56 }
57 
58 bool CCoins::Spend(int nPos)
59 {
60  CTxInUndo undo;
61  COutPoint out(UINT256_ZERO, nPos);
62  return Spend(out, undo);
63 }
64 
65 
66 bool CCoinsView::GetCoins(const uint256& txid, CCoins& coins) const { return false; }
67 bool CCoinsView::HaveCoins(const uint256& txid) const { return false; }
69 bool CCoinsView::BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock) { return false; }
70 bool CCoinsView::GetStats(CCoinsStats& stats) const { return false; }
71 
72 
74 bool CCoinsViewBacked::GetCoins(const uint256& txid, CCoins& coins) const { return base->GetCoins(txid, coins); }
75 bool CCoinsViewBacked::HaveCoins(const uint256& txid) const { return base->HaveCoins(txid); }
77 void CCoinsViewBacked::SetBackend(CCoinsView& viewIn) { base = &viewIn; }
78 bool CCoinsViewBacked::BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
79 bool CCoinsViewBacked::GetStats(CCoinsStats& stats) const { return base->GetStats(stats); }
80 
82 
83 CCoinsViewCache::CCoinsViewCache(CCoinsView* baseIn) : CCoinsViewBacked(baseIn), hasModifier(false), cachedCoinsUsage(0) {}
84 
86 {
87  assert(!hasModifier);
88 }
89 
91  return memusage::DynamicUsage(cacheCoins) + cachedCoinsUsage;
92 }
93 
94 CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256& txid) const
95 {
96  CCoinsMap::iterator it = cacheCoins.find(txid);
97  if (it != cacheCoins.end())
98  return it;
99  CCoins tmp;
100  if (!base->GetCoins(txid, tmp))
101  return cacheCoins.end();
102  CCoinsMap::iterator ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry())).first;
103  tmp.swap(ret->second.coins);
104  if (ret->second.coins.IsPruned()) {
105  // The parent only has an empty entry for this txid; we can consider our
106  // version as fresh.
107  ret->second.flags = CCoinsCacheEntry::FRESH;
108  cachedCoinsUsage += memusage::DynamicUsage(ret->second.coins);
109  }
110  return ret;
111 }
112 
113 bool CCoinsViewCache::GetCoins(const uint256& txid, CCoins& coins) const
114 {
115  CCoinsMap::const_iterator it = FetchCoins(txid);
116  if (it != cacheCoins.end()) {
117  coins = it->second.coins;
118  return true;
119  }
120  return false;
121 }
122 
124 {
125  assert(!hasModifier);
126  std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry()));
127  size_t cachedCoinUsage = 0;
128  if (ret.second) {
129  if (!base->GetCoins(txid, ret.first->second.coins)) {
130  // The parent view does not have this entry; mark it as fresh.
131  ret.first->second.coins.Clear();
132  ret.first->second.flags = CCoinsCacheEntry::FRESH;
133  } else if (ret.first->second.coins.IsPruned()) {
134  // The parent view only has a pruned entry for this; mark it as fresh.
135  ret.first->second.flags = CCoinsCacheEntry::FRESH;
136  }
137  } else {
138  cachedCoinUsage = memusage::DynamicUsage(ret.first->second.coins);
139  }
140  // Assume that whenever ModifyCoins is called, the entry will be modified.
141  ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
142  return CCoinsModifier(*this, ret.first, cachedCoinUsage);
143 }
144 
145 const CCoins* CCoinsViewCache::AccessCoins(const uint256& txid) const
146 {
147  CCoinsMap::const_iterator it = FetchCoins(txid);
148  if (it == cacheCoins.end()) {
149  return NULL;
150  } else {
151  return &it->second.coins;
152  }
153 }
154 
155 bool CCoinsViewCache::HaveCoins(const uint256& txid) const
156 {
157  CCoinsMap::const_iterator it = FetchCoins(txid);
158  // We're using vtx.empty() instead of IsPruned here for performance reasons,
159  // as we only care about the case where a transaction was replaced entirely
160  // in a reorganization (which wipes vout entirely, as opposed to spending
161  // which just cleans individual outputs).
162  return (it != cacheCoins.end() && !it->second.coins.vout.empty());
163 }
164 
166 {
167  if (hashBlock.IsNull())
169  return hashBlock;
170 }
171 
172 void CCoinsViewCache::SetBestBlock(const uint256& hashBlockIn)
173 {
174  hashBlock = hashBlockIn;
175 }
176 
177 bool CCoinsViewCache::BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlockIn)
178 {
179  assert(!hasModifier);
180  for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
181  if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
182  CCoinsMap::iterator itUs = cacheCoins.find(it->first);
183  if (itUs == cacheCoins.end()) {
184  // The parent cache does not have an entry, while the child does
185  // We can ignore it if it's both FRESH and pruned in the child
186  if (!(it->second.flags & CCoinsCacheEntry::FRESH && it->second.coins.IsPruned())) {
187  // Otherwise we will need to create it in the parent
188  // and move the data up and mark it as dirty
189  CCoinsCacheEntry& entry = cacheCoins[it->first];
190  entry.coins.swap(it->second.coins);
191  cachedCoinsUsage += memusage::DynamicUsage(entry.coins);
193  // We can mark it FRESH in the parent if it was FRESH in the child
194  // Otherwise it might have just been flushed from the parent's cache
195  // and already exist in the grandparent
196  if (it->second.flags & CCoinsCacheEntry::FRESH)
198  }
199  } else {
200  // Found the entry in the parent cache
201  if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
202  // The grandparent does not have an entry, and the child is
203  // modified and being pruned. This means we can just delete
204  // it from the parent.
205  cachedCoinsUsage -= memusage::DynamicUsage(itUs->second.coins);
206  cacheCoins.erase(itUs);
207  } else {
208  // A normal modification.
209  cachedCoinsUsage -= memusage::DynamicUsage(itUs->second.coins);
210  itUs->second.coins.swap(it->second.coins);
211  cachedCoinsUsage += memusage::DynamicUsage(itUs->second.coins);
212  itUs->second.flags |= CCoinsCacheEntry::DIRTY;
213  }
214  }
215  }
216  CCoinsMap::iterator itOld = it++;
217  mapCoins.erase(itOld);
218  }
219  hashBlock = hashBlockIn;
220  return true;
221 }
222 
224 {
225  bool fOk = base->BatchWrite(cacheCoins, hashBlock);
226  cacheCoins.clear();
227  cachedCoinsUsage = 0;
228  return fOk;
229 }
230 
231 unsigned int CCoinsViewCache::GetCacheSize() const
232 {
233  return cacheCoins.size();
234 }
235 
236 const CTxOut& CCoinsViewCache::GetOutputFor(const CTxIn& input) const
237 {
238  const CCoins* coins = AccessCoins(input.prevout.hash);
239  assert(coins && coins->IsAvailable(input.prevout.n));
240  return coins->vout[input.prevout.n];
241 }
242 
244 {
245  if (!tx.IsCoinBase()) {
246  for (unsigned int i = 0; i < tx.vin.size(); i++) {
247  const COutPoint& prevout = tx.vin[i].prevout;
248  const CCoins* coins = AccessCoins(prevout.hash);
249 
250  if (!coins || !coins->IsAvailable(prevout.n)) {
251  return false;
252  }
253  }
254  }
255  return true;
256 }
257 
258 CCoinsModifier::CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_, size_t usage) : cache(cache_), it(it_), cachedCoinUsage(usage)
259 {
260  assert(!cache.hasModifier);
261  cache.hasModifier = true;
262 }
263 
265 {
266  assert(cache.hasModifier);
267  cache.hasModifier = false;
268  it->second.coins.Cleanup();
269  cache.cachedCoinsUsage -= cachedCoinUsage; // Subtract the old usage
270  if ((it->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
271  cache.cacheCoins.erase(it);
272  } else {
273  // If the coin still exists after the modification, add the new usage
274  cache.cachedCoinsUsage += memusage::DynamicUsage(it->second.coins);
275  }
276 }
CCoinsViewBacked::SetBackend
void SetBackend(CCoinsView &viewIn)
Definition: coins.cpp:77
CTxIn
An input of a transaction.
Definition: transaction.h:83
UINT256_ZERO
const uint256 UINT256_ZERO
constant uint256 instances
Definition: uint256.h:129
CCoinsKeyHasher::CCoinsKeyHasher
CCoinsKeyHasher()
Definition: coins.cpp:81
CCoinsViewCache::GetCacheSize
unsigned int GetCacheSize() const
Calculate the size of the cache (in number of transactions)
Definition: coins.cpp:231
CCoinsModifier::~CCoinsModifier
~CCoinsModifier()
Definition: coins.cpp:264
CCoinsViewCache::ModifyCoins
CCoinsModifier ModifyCoins(const uint256 &txid)
Return a modifiable reference to a CCoins.
Definition: coins.cpp:123
CCoins::Cleanup
void Cleanup()
remove spent outputs at the end of vout
Definition: coins.h:123
b
void const uint64_t * b
Definition: field_5x52_asm_impl.h:10
CCoinsViewBacked::GetStats
bool GetStats(CCoinsStats &stats) const
Calculate statistics about the unspent transaction output set.
Definition: coins.cpp:79
CCoinsModifier::CCoinsModifier
CCoinsModifier(CCoinsViewCache &cache_, CCoinsMap::iterator it_, size_t usage)
Definition: coins.cpp:258
CCoinsViewCache::CCoinsViewCache
CCoinsViewCache(CCoinsView *baseIn)
Definition: coins.cpp:83
CCoinsViewCache::GetOutputFor
const CTxOut & GetOutputFor(const CTxIn &input) const
Definition: coins.cpp:236
CTxInUndo::nVersion
int nVersion
Definition: undo.h:27
COutPoint::hash
uint256 hash
Definition: transaction.h:39
CCoinsModifier::cachedCoinUsage
size_t cachedCoinUsage
Definition: coins.h:403
CCoinsViewCache::cacheCoins
CCoinsMap cacheCoins
Definition: coins.h:425
CCoins::IsAvailable
bool IsAvailable(unsigned int nPos) const
check whether a particular output is still available
Definition: coins.h:275
CCoinsStats
Definition: coins.h:332
CTxInUndo::fCoinStake
bool fCoinStake
Definition: undo.h:25
CCoinsViewCache::CCoinsModifier
friend class CCoinsModifier
Definition: coins.h:473
CCoins::nHeight
int nHeight
at which height this transaction was included in the active block chain
Definition: coins.h:88
CTxInUndo::nHeight
unsigned int nHeight
Definition: undo.h:26
CTransaction
The basic transaction that is broadcasted on the network and contained in blocks.
Definition: transaction.h:269
CCoinsViewBacked::base
CCoinsView * base
Definition: coins.h:375
CCoinsViewCache::~CCoinsViewCache
~CCoinsViewCache()
Definition: coins.cpp:85
CCoinsView
Abstract view on the open txout dataset.
Definition: coins.h:346
CCoinsViewBacked::BatchWrite
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock)
Do a bulk modification (multiple CCoins changes + BestBlock change).
Definition: coins.cpp:78
CCoinsViewCache::hasModifier
bool hasModifier
Definition: coins.h:418
CCoinsView::BatchWrite
virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock)
Do a bulk modification (multiple CCoins changes + BestBlock change).
Definition: coins.cpp:69
CTransaction::IsCoinBase
bool IsCoinBase() const
Definition: transaction.h:359
CCoinsView::GetCoins
virtual bool GetCoins(const uint256 &txid, CCoins &coins) const
Retrieve the CCoins (unspent transaction outputs) for a given txid.
Definition: coins.cpp:66
CCoins::vout
std::vector< CTxOut > vout
unspent transaction outputs; spent outputs are .IsNull(); spent outputs at the end of the array are d...
Definition: coins.h:85
CCoins::swap
void swap(CCoins &to)
Definition: coins.h:140
random.h
CTxOut
An output of a transaction.
Definition: transaction.h:164
CCoinsViewCache::DynamicMemoryUsage
size_t DynamicMemoryUsage() const
Calculate the size of the cache (in bytes)
Definition: coins.cpp:90
CCoinsModifier::it
CCoinsMap::iterator it
Definition: coins.h:402
CCoinsModifier
A reference to a mutable cache entry.
Definition: coins.h:398
CCoinsViewBacked::HaveCoins
bool HaveCoins(const uint256 &txid) const
Just check whether we have data for a given txid.
Definition: coins.cpp:75
GetRandHash
uint256 GetRandHash()
Definition: random.cpp:371
CCoinsCacheEntry::coins
CCoins coins
Definition: coins.h:319
CCoinsCacheEntry::flags
unsigned char flags
Definition: coins.h:320
CCoinsViewCache::hashBlock
uint256 hashBlock
Make mutable so that we can "fill the cache" even from Get-methods declared as "const".
Definition: coins.h:424
uint256
256-bit unsigned big integer.
Definition: uint256.h:38
base_uint::IsNull
bool IsNull() const
Definition: arith_uint256.h:312
coins.h
CCoinsViewCache::AccessCoins
const CCoins * AccessCoins(const uint256 &txid) const
Return a pointer to CCoins in the cache, or NULL if not found.
Definition: coins.cpp:145
CCoinsViewBacked::CCoinsViewBacked
CCoinsViewBacked(CCoinsView *viewIn)
Definition: coins.cpp:73
CCoinsViewBacked::GetCoins
bool GetCoins(const uint256 &txid, CCoins &coins) const
Retrieve the CCoins (unspent transaction outputs) for a given txid.
Definition: coins.cpp:74
CCoins::nVersion
int nVersion
version of the CTransaction; accesses to this value should probably check for nHeight as well,...
Definition: coins.h:92
CCoinsViewCache::cachedCoinsUsage
size_t cachedCoinsUsage
Definition: coins.h:428
CCoinsViewCache::BatchWrite
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock)
Do a bulk modification (multiple CCoins changes + BestBlock change).
Definition: coins.cpp:177
CCoinsViewCache
CCoinsView that adds a memory cache for transactions to another CCoinsView.
Definition: coins.h:414
CCoinsView::GetStats
virtual bool GetStats(CCoinsStats &stats) const
Calculate statistics about the unspent transaction output set.
Definition: coins.cpp:70
CCoinsViewBacked
CCoinsView backed by another CCoinsView.
Definition: coins.h:372
memusage.h
CCoinsViewCache::SetBestBlock
void SetBestBlock(const uint256 &hashBlock)
Definition: coins.cpp:172
COutPoint::n
uint32_t n
Definition: transaction.h:40
CCoinsViewCache::HaveCoins
bool HaveCoins(const uint256 &txid) const
Just check whether we have data for a given txid.
Definition: coins.cpp:155
CTransaction::vin
std::vector< CTxIn > vin
Definition: transaction.h:285
CTxIn::prevout
COutPoint prevout
Definition: transaction.h:86
CCoinsViewCache::HaveInputs
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:243
CCoinsMap
boost::unordered_map< uint256, CCoinsCacheEntry, CCoinsKeyHasher > CCoinsMap
Definition: coins.h:330
CCoins::fCoinStake
bool fCoinStake
Definition: coins.h:82
CTxInUndo
Undo information for a CTxIn.
Definition: undo.h:20
CCoins
Definition: coins.h:77
CCoins::fCoinBase
bool fCoinBase
whether transaction is a coinbase
Definition: coins.h:81
CCoinsViewBacked::GetBestBlock
uint256 GetBestBlock() const
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: coins.cpp:76
CCoinsViewCache::GetBestBlock
uint256 GetBestBlock() const
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: coins.cpp:165
COutPoint
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:36
CCoins::Spend
bool Spend(const COutPoint &out, CTxInUndo &undo)
mark an outpoint spent, and construct undo information
Definition: coins.cpp:38
CCoinsCacheEntry::FRESH
@ FRESH
Definition: coins.h:324
CCoinsCacheEntry::DIRTY
@ DIRTY
Definition: coins.h:323
CCoinsView::HaveCoins
virtual bool HaveCoins(const uint256 &txid) const
Just check whether we have data for a given txid.
Definition: coins.cpp:67
CCoins::CalcMaskSize
void CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const
calculate number of bytes for the bitmask, and its number of non-zero bytes each bit in the bitmask r...
Definition: coins.cpp:19
CCoinsView::GetBestBlock
virtual uint256 GetBestBlock() const
Retrieve the block hash whose state this CCoinsView currently represents.
Definition: coins.cpp:68
CCoinsViewCache::FetchCoins
CCoinsMap::iterator FetchCoins(const uint256 &txid)
CCoinsModifier::cache
CCoinsViewCache & cache
Definition: coins.h:401
CCoinsViewCache::GetCoins
bool GetCoins(const uint256 &txid, CCoins &coins) const
Retrieve the CCoins (unspent transaction outputs) for a given txid.
Definition: coins.cpp:113
CCoinsCacheEntry
Definition: coins.h:318
CCoinsViewCache::Flush
bool Flush()
Push the modifications applied to this cache to its base.
Definition: coins.cpp:223
CTxInUndo::fCoinBase
bool fCoinBase
Definition: undo.h:24