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.
13 * calculate number of bytes for the bitmask, and its number of non-zero bytes
14 * each bit in the bitmask represents the availability of one output, but the
15 * availabilities of the first two outputs are encoded separately
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++) {
21 for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++) {
22 if (!vout[2+b*8+i].IsNull()) {
28 nLastUsedByte = b + 1;
32 nBytes += nLastUsedByte;
35 bool CCoins::Spend(uint32_t nPos)
37 if (nPos >= vout.size() || vout[nPos].IsNull())
43 bool CCoinsView::GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const { return false; }
44 bool CCoinsView::GetSerial(const uint256 &serial) const { return false; }
45 bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; }
46 bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; }
47 uint256 CCoinsView::GetBestBlock() const { return uint256(); }
48 uint256 CCoinsView::GetBestAnchor() const { return uint256(); };
49 bool CCoinsView::BatchWrite(CCoinsMap &mapCoins,
50 const uint256 &hashBlock,
51 const uint256 &hashAnchor,
52 CAnchorsMap &mapAnchors,
53 CSerialsMap &mapSerials) { return false; }
54 bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; }
57 CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { }
59 bool CCoinsViewBacked::GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const { return base->GetAnchorAt(rt, tree); }
60 bool CCoinsViewBacked::GetSerial(const uint256 &serial) const { return base->GetSerial(serial); }
61 bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); }
62 bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); }
63 uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
64 uint256 CCoinsViewBacked::GetBestAnchor() const { return base->GetBestAnchor(); }
65 void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
66 bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins,
67 const uint256 &hashBlock,
68 const uint256 &hashAnchor,
69 CAnchorsMap &mapAnchors,
70 CSerialsMap &mapSerials) { return base->BatchWrite(mapCoins, hashBlock, hashAnchor, mapAnchors, mapSerials); }
71 bool CCoinsViewBacked::GetStats(CCoinsStats &stats) const { return base->GetStats(stats); }
73 CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {}
75 CCoinsViewCache::CCoinsViewCache(CCoinsView *baseIn) : CCoinsViewBacked(baseIn), hasModifier(false), cachedCoinsUsage(0) { }
77 CCoinsViewCache::~CCoinsViewCache()
82 size_t CCoinsViewCache::DynamicMemoryUsage() const {
83 return memusage::DynamicUsage(cacheCoins) + cachedCoinsUsage;
86 CCoinsMap::const_iterator CCoinsViewCache::FetchCoins(const uint256 &txid) const {
87 CCoinsMap::iterator it = cacheCoins.find(txid);
88 if (it != cacheCoins.end())
91 if (!base->GetCoins(txid, tmp))
92 return cacheCoins.end();
93 CCoinsMap::iterator ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry())).first;
94 tmp.swap(ret->second.coins);
95 if (ret->second.coins.IsPruned()) {
96 // The parent only has an empty entry for this txid; we can consider our
98 ret->second.flags = CCoinsCacheEntry::FRESH;
100 cachedCoinsUsage += memusage::DynamicUsage(ret->second.coins);
105 bool CCoinsViewCache::GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const {
106 CAnchorsMap::const_iterator it = cacheAnchors.find(rt);
107 if (it != cacheAnchors.end()) {
108 if (it->second.entered) {
109 tree.setTo(it->second.tree);
116 CAnchorsCacheEntry entry;
117 if (!base->GetAnchorAt(rt, tree)) {
121 entry.entered = true;
122 entry.tree.setTo(tree);
123 cacheAnchors.insert(std::make_pair(rt, entry));
128 bool CCoinsViewCache::GetSerial(const uint256 &serial) const {
129 CSerialsMap::iterator it = cacheSerials.find(serial);
130 if (it != cacheSerials.end())
131 return it->second.entered;
133 CSerialsCacheEntry entry;
134 bool tmp = base->GetSerial(serial);
137 cacheSerials.insert(std::make_pair(serial, entry));
144 void CCoinsViewCache::PushAnchor(const libzerocash::IncrementalMerkleTree &tree) {
145 std::vector<unsigned char> newrt_v(32);
146 tree.getRootValue(newrt_v);
147 uint256 newrt(newrt_v);
149 auto currentRoot = GetBestAnchor();
151 // We don't want to overwrite an anchor we already have.
152 // This occurs when a block doesn't modify mapAnchors at all,
153 // because there are no pours. We could get around this a
154 // different way (make all blocks modify mapAnchors somehow)
155 // but this is simpler to reason about.
156 if (currentRoot != newrt) {
157 CAnchorsMap::iterator ret = cacheAnchors.insert(std::make_pair(newrt, CAnchorsCacheEntry())).first;
159 ret->second.entered = true;
160 ret->second.tree.setTo(tree);
161 ret->second.flags = CAnchorsCacheEntry::DIRTY;
167 void CCoinsViewCache::PopAnchor(const uint256 &newrt) {
168 auto currentRoot = GetBestAnchor();
170 // Blocks might not change the commitment tree, in which
171 // case restoring the "old" anchor during a reorg must
173 if (currentRoot != newrt) {
174 CAnchorsMap::iterator ret = cacheAnchors.insert(std::make_pair(currentRoot, CAnchorsCacheEntry())).first;
176 ret->second.entered = false;
177 ret->second.flags = CAnchorsCacheEntry::DIRTY;
183 void CCoinsViewCache::SetSerial(const uint256 &serial, bool spent) {
184 std::pair<CSerialsMap::iterator, bool> ret = cacheSerials.insert(std::make_pair(serial, CSerialsCacheEntry()));
185 ret.first->second.entered = spent;
186 ret.first->second.flags |= CSerialsCacheEntry::DIRTY;
189 bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) const {
190 CCoinsMap::const_iterator it = FetchCoins(txid);
191 if (it != cacheCoins.end()) {
192 coins = it->second.coins;
198 CCoinsModifier CCoinsViewCache::ModifyCoins(const uint256 &txid) {
199 assert(!hasModifier);
200 std::pair<CCoinsMap::iterator, bool> ret = cacheCoins.insert(std::make_pair(txid, CCoinsCacheEntry()));
201 size_t cachedCoinUsage = 0;
203 if (!base->GetCoins(txid, ret.first->second.coins)) {
204 // The parent view does not have this entry; mark it as fresh.
205 ret.first->second.coins.Clear();
206 ret.first->second.flags = CCoinsCacheEntry::FRESH;
207 } else if (ret.first->second.coins.IsPruned()) {
208 // The parent view only has a pruned entry for this; mark it as fresh.
209 ret.first->second.flags = CCoinsCacheEntry::FRESH;
212 cachedCoinUsage = memusage::DynamicUsage(ret.first->second.coins);
214 // Assume that whenever ModifyCoins is called, the entry will be modified.
215 ret.first->second.flags |= CCoinsCacheEntry::DIRTY;
216 return CCoinsModifier(*this, ret.first, cachedCoinUsage);
219 const CCoins* CCoinsViewCache::AccessCoins(const uint256 &txid) const {
220 CCoinsMap::const_iterator it = FetchCoins(txid);
221 if (it == cacheCoins.end()) {
224 return &it->second.coins;
228 bool CCoinsViewCache::HaveCoins(const uint256 &txid) const {
229 CCoinsMap::const_iterator it = FetchCoins(txid);
230 // We're using vtx.empty() instead of IsPruned here for performance reasons,
231 // as we only care about the case where a transaction was replaced entirely
232 // in a reorganization (which wipes vout entirely, as opposed to spending
233 // which just cleans individual outputs).
234 return (it != cacheCoins.end() && !it->second.coins.vout.empty());
237 uint256 CCoinsViewCache::GetBestBlock() const {
238 if (hashBlock.IsNull())
239 hashBlock = base->GetBestBlock();
244 uint256 CCoinsViewCache::GetBestAnchor() const {
245 if (hashAnchor.IsNull())
246 hashAnchor = base->GetBestAnchor();
250 void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
251 hashBlock = hashBlockIn;
254 bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins,
255 const uint256 &hashBlockIn,
256 const uint256 &hashAnchorIn,
257 CAnchorsMap &mapAnchors,
258 CSerialsMap &mapSerials) {
259 assert(!hasModifier);
260 for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
261 if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
262 CCoinsMap::iterator itUs = cacheCoins.find(it->first);
263 if (itUs == cacheCoins.end()) {
264 if (!it->second.coins.IsPruned()) {
265 // The parent cache does not have an entry, while the child
266 // cache does have (a non-pruned) one. Move the data up, and
267 // mark it as fresh (if the grandparent did have it, we
268 // would have pulled it in at first GetCoins).
269 assert(it->second.flags & CCoinsCacheEntry::FRESH);
270 CCoinsCacheEntry& entry = cacheCoins[it->first];
271 entry.coins.swap(it->second.coins);
272 cachedCoinsUsage += memusage::DynamicUsage(entry.coins);
273 entry.flags = CCoinsCacheEntry::DIRTY | CCoinsCacheEntry::FRESH;
276 if ((itUs->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
277 // The grandparent does not have an entry, and the child is
278 // modified and being pruned. This means we can just delete
279 // it from the parent.
280 cachedCoinsUsage -= memusage::DynamicUsage(itUs->second.coins);
281 cacheCoins.erase(itUs);
283 // A normal modification.
284 cachedCoinsUsage -= memusage::DynamicUsage(itUs->second.coins);
285 itUs->second.coins.swap(it->second.coins);
286 cachedCoinsUsage += memusage::DynamicUsage(itUs->second.coins);
287 itUs->second.flags |= CCoinsCacheEntry::DIRTY;
291 CCoinsMap::iterator itOld = it++;
292 mapCoins.erase(itOld);
295 for (CAnchorsMap::iterator child_it = mapAnchors.begin(); child_it != mapAnchors.end();)
297 if (child_it->second.flags & CAnchorsCacheEntry::DIRTY) {
298 CAnchorsMap::iterator parent_it = cacheAnchors.find(child_it->first);
300 if (parent_it == cacheAnchors.end()) {
301 if (child_it->second.entered) {
302 // Parent doesn't have an entry, but child has a new commitment root.
304 CAnchorsCacheEntry& entry = cacheAnchors[child_it->first];
305 entry.entered = true;
306 entry.tree.setTo(child_it->second.tree);
307 entry.flags = CAnchorsCacheEntry::DIRTY;
312 if (parent_it->second.entered != child_it->second.entered) {
313 // The parent may have removed the entry.
314 parent_it->second.entered = child_it->second.entered;
315 parent_it->second.flags |= CAnchorsCacheEntry::DIRTY;
320 CAnchorsMap::iterator itOld = child_it++;
321 mapAnchors.erase(itOld);
324 for (CSerialsMap::iterator child_it = mapSerials.begin(); child_it != mapSerials.end();)
326 if (child_it->second.flags & CSerialsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
327 CSerialsMap::iterator parent_it = cacheSerials.find(child_it->first);
329 if (parent_it == cacheSerials.end()) {
330 if (child_it->second.entered) {
331 // Parent doesn't have an entry, but child has a SPENT serial.
332 // Move the spent serial up.
334 CSerialsCacheEntry& entry = cacheSerials[child_it->first];
335 entry.entered = true;
336 entry.flags = CSerialsCacheEntry::DIRTY;
341 if (parent_it->second.entered != child_it->second.entered) {
342 parent_it->second.entered = child_it->second.entered;
343 parent_it->second.flags |= CSerialsCacheEntry::DIRTY;
347 CSerialsMap::iterator itOld = child_it++;
348 mapSerials.erase(itOld);
351 hashAnchor = hashAnchorIn;
352 hashBlock = hashBlockIn;
356 bool CCoinsViewCache::Flush() {
357 bool fOk = base->BatchWrite(cacheCoins, hashBlock, hashAnchor, cacheAnchors, cacheSerials);
359 cacheAnchors.clear();
360 cacheSerials.clear();
361 cachedCoinsUsage = 0;
365 unsigned int CCoinsViewCache::GetCacheSize() const {
366 return cacheCoins.size();
369 const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) const
371 const CCoins* coins = AccessCoins(input.prevout.hash);
372 assert(coins && coins->IsAvailable(input.prevout.n));
373 return coins->vout[input.prevout.n];
376 CAmount CCoinsViewCache::GetValueIn(const CTransaction& tx) const
382 for (unsigned int i = 0; i < tx.vin.size(); i++)
383 nResult += GetOutputFor(tx.vin[i]).nValue;
385 nResult += tx.GetPourValueIn();
390 bool CCoinsViewCache::HavePourRequirements(const CTransaction& tx) const
392 BOOST_FOREACH(const CPourTx &pour, tx.vpour)
394 BOOST_FOREACH(const uint256& serial, pour.serials)
396 if (GetSerial(serial)) {
397 // If the serial is set, this transaction
403 libzerocash::IncrementalMerkleTree tree(INCREMENTAL_MERKLE_TREE_DEPTH);
404 if (!GetAnchorAt(pour.anchor, tree)) {
405 // If we do not have the anchor for the pour,
414 bool CCoinsViewCache::HaveInputs(const CTransaction& tx) const
416 if (!tx.IsCoinBase()) {
417 for (unsigned int i = 0; i < tx.vin.size(); i++) {
418 const COutPoint &prevout = tx.vin[i].prevout;
419 const CCoins* coins = AccessCoins(prevout.hash);
420 if (!coins || !coins->IsAvailable(prevout.n)) {
428 double CCoinsViewCache::GetPriority(const CTransaction &tx, int nHeight) const
432 double dResult = 0.0;
433 BOOST_FOREACH(const CTxIn& txin, tx.vin)
435 const CCoins* coins = AccessCoins(txin.prevout.hash);
437 if (!coins->IsAvailable(txin.prevout.n)) continue;
438 if (coins->nHeight < nHeight) {
439 dResult += coins->vout[txin.prevout.n].nValue * (nHeight-coins->nHeight);
442 return tx.ComputePriority(dResult);
445 CCoinsModifier::CCoinsModifier(CCoinsViewCache& cache_, CCoinsMap::iterator it_, size_t usage) : cache(cache_), it(it_), cachedCoinUsage(usage) {
446 assert(!cache.hasModifier);
447 cache.hasModifier = true;
450 CCoinsModifier::~CCoinsModifier()
452 assert(cache.hasModifier);
453 cache.hasModifier = false;
454 it->second.coins.Cleanup();
455 cache.cachedCoinsUsage -= cachedCoinUsage; // Subtract the old usage
456 if ((it->second.flags & CCoinsCacheEntry::FRESH) && it->second.coins.IsPruned()) {
457 cache.cacheCoins.erase(it);
459 // If the coin still exists after the modification, add the new usage
460 cache.cachedCoinsUsage += memusage::DynamicUsage(it->second.coins);