forked from bitcoin/bitcoin
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move CCoins-related logic to coins.{cpp.h}
- Loading branch information
Showing
10 changed files
with
581 additions
and
577 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
// Copyright (c) 2012-2013 The Bitcoin developers | ||
// Distributed under the MIT/X11 software license, see the accompanying | ||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
|
||
#include "coins.h" | ||
|
||
#include <assert.h> | ||
|
||
// calculate number of bytes for the bitmask, and its number of non-zero bytes | ||
// each bit in the bitmask represents the availability of one output, but the | ||
// availabilities of the first two outputs are encoded separately | ||
void CCoins::CalcMaskSize(unsigned int &nBytes, unsigned int &nNonzeroBytes) const { | ||
unsigned int nLastUsedByte = 0; | ||
for (unsigned int b = 0; 2+b*8 < vout.size(); b++) { | ||
bool fZero = true; | ||
for (unsigned int i = 0; i < 8 && 2+b*8+i < vout.size(); i++) { | ||
if (!vout[2+b*8+i].IsNull()) { | ||
fZero = false; | ||
continue; | ||
} | ||
} | ||
if (!fZero) { | ||
nLastUsedByte = b + 1; | ||
nNonzeroBytes++; | ||
} | ||
} | ||
nBytes += nLastUsedByte; | ||
} | ||
|
||
bool CCoins::Spend(const COutPoint &out, CTxInUndo &undo) { | ||
if (out.n >= vout.size()) | ||
return false; | ||
if (vout[out.n].IsNull()) | ||
return false; | ||
undo = CTxInUndo(vout[out.n]); | ||
vout[out.n].SetNull(); | ||
Cleanup(); | ||
if (vout.size() == 0) { | ||
undo.nHeight = nHeight; | ||
undo.fCoinBase = fCoinBase; | ||
undo.nVersion = this->nVersion; | ||
} | ||
return true; | ||
} | ||
|
||
bool CCoins::Spend(int nPos) { | ||
CTxInUndo undo; | ||
COutPoint out(0, nPos); | ||
return Spend(out, undo); | ||
} | ||
|
||
|
||
bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) { return false; } | ||
bool CCoinsView::SetCoins(const uint256 &txid, const CCoins &coins) { return false; } | ||
bool CCoinsView::HaveCoins(const uint256 &txid) { return false; } | ||
uint256 CCoinsView::GetBestBlock() { return uint256(0); } | ||
bool CCoinsView::SetBestBlock(const uint256 &hashBlock) { return false; } | ||
bool CCoinsView::BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock) { return false; } | ||
bool CCoinsView::GetStats(CCoinsStats &stats) { return false; } | ||
|
||
|
||
CCoinsViewBacked::CCoinsViewBacked(CCoinsView &viewIn) : base(&viewIn) { } | ||
bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) { return base->GetCoins(txid, coins); } | ||
bool CCoinsViewBacked::SetCoins(const uint256 &txid, const CCoins &coins) { return base->SetCoins(txid, coins); } | ||
bool CCoinsViewBacked::HaveCoins(const uint256 &txid) { return base->HaveCoins(txid); } | ||
uint256 CCoinsViewBacked::GetBestBlock() { return base->GetBestBlock(); } | ||
bool CCoinsViewBacked::SetBestBlock(const uint256 &hashBlock) { return base->SetBestBlock(hashBlock); } | ||
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; } | ||
bool CCoinsViewBacked::BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); } | ||
bool CCoinsViewBacked::GetStats(CCoinsStats &stats) { return base->GetStats(stats); } | ||
|
||
CCoinsViewCache::CCoinsViewCache(CCoinsView &baseIn, bool fDummy) : CCoinsViewBacked(baseIn), hashBlock(0) { } | ||
|
||
bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) { | ||
if (cacheCoins.count(txid)) { | ||
coins = cacheCoins[txid]; | ||
return true; | ||
} | ||
if (base->GetCoins(txid, coins)) { | ||
cacheCoins[txid] = coins; | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
std::map<uint256,CCoins>::iterator CCoinsViewCache::FetchCoins(const uint256 &txid) { | ||
std::map<uint256,CCoins>::iterator it = cacheCoins.lower_bound(txid); | ||
if (it != cacheCoins.end() && it->first == txid) | ||
return it; | ||
CCoins tmp; | ||
if (!base->GetCoins(txid,tmp)) | ||
return cacheCoins.end(); | ||
std::map<uint256,CCoins>::iterator ret = cacheCoins.insert(it, std::make_pair(txid, CCoins())); | ||
tmp.swap(ret->second); | ||
return ret; | ||
} | ||
|
||
CCoins &CCoinsViewCache::GetCoins(const uint256 &txid) { | ||
std::map<uint256,CCoins>::iterator it = FetchCoins(txid); | ||
assert(it != cacheCoins.end()); | ||
return it->second; | ||
} | ||
|
||
bool CCoinsViewCache::SetCoins(const uint256 &txid, const CCoins &coins) { | ||
cacheCoins[txid] = coins; | ||
return true; | ||
} | ||
|
||
bool CCoinsViewCache::HaveCoins(const uint256 &txid) { | ||
return FetchCoins(txid) != cacheCoins.end(); | ||
} | ||
|
||
uint256 CCoinsViewCache::GetBestBlock() { | ||
if (hashBlock == uint256(0)) | ||
hashBlock = base->GetBestBlock(); | ||
return hashBlock; | ||
} | ||
|
||
bool CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) { | ||
hashBlock = hashBlockIn; | ||
return true; | ||
} | ||
|
||
bool CCoinsViewCache::BatchWrite(const std::map<uint256, CCoins> &mapCoins, const uint256 &hashBlockIn) { | ||
for (std::map<uint256, CCoins>::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++) | ||
cacheCoins[it->first] = it->second; | ||
hashBlock = hashBlockIn; | ||
return true; | ||
} | ||
|
||
bool CCoinsViewCache::Flush() { | ||
bool fOk = base->BatchWrite(cacheCoins, hashBlock); | ||
if (fOk) | ||
cacheCoins.clear(); | ||
return fOk; | ||
} | ||
|
||
unsigned int CCoinsViewCache::GetCacheSize() { | ||
return cacheCoins.size(); | ||
} | ||
|
||
const CTxOut &CCoinsViewCache::GetOutputFor(const CTxIn& input) | ||
{ | ||
const CCoins &coins = GetCoins(input.prevout.hash); | ||
assert(coins.IsAvailable(input.prevout.n)); | ||
return coins.vout[input.prevout.n]; | ||
} | ||
|
||
int64_t CCoinsViewCache::GetValueIn(const CTransaction& tx) | ||
{ | ||
if (tx.IsCoinBase()) | ||
return 0; | ||
|
||
int64_t nResult = 0; | ||
for (unsigned int i = 0; i < tx.vin.size(); i++) | ||
nResult += GetOutputFor(tx.vin[i]).nValue; | ||
|
||
return nResult; | ||
} | ||
|
||
bool CCoinsViewCache::HaveInputs(const CTransaction& tx) | ||
{ | ||
if (!tx.IsCoinBase()) { | ||
// first check whether information about the prevout hash is available | ||
for (unsigned int i = 0; i < tx.vin.size(); i++) { | ||
const COutPoint &prevout = tx.vin[i].prevout; | ||
if (!HaveCoins(prevout.hash)) | ||
return false; | ||
} | ||
|
||
// then check whether the actual outputs are available | ||
for (unsigned int i = 0; i < tx.vin.size(); i++) { | ||
const COutPoint &prevout = tx.vin[i].prevout; | ||
const CCoins &coins = GetCoins(prevout.hash); | ||
if (!coins.IsAvailable(prevout.n)) | ||
return false; | ||
} | ||
} | ||
return true; | ||
} |
Oops, something went wrong.