aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2013-11-10 18:09:58 -0800
committerGavin Andresen <gavinandresen@gmail.com>2013-11-10 18:09:58 -0800
commit7d7df381f85112f5d00dc8f164451dea5baa48bb (patch)
tree624d282fc308688102fa17c1fd331e99e9ac0720 /src/main.cpp
parent16d5f2c5e0a7276fb2b09d8dd51b7bac2753c4cc (diff)
parenta0fa20a12b69717636050dd8742713b1d82ae524 (diff)
downloadbitcoin-7d7df381f85112f5d00dc8f164451dea5baa48bb.tar.xz
Merge pull request #3199 from sipa/mempoolmove
Cleanup refactoring of coins/mempool
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp195
1 files changed, 19 insertions, 176 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 11f262d9cb..8aef91d829 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -229,128 +229,6 @@ CBlockIndex *CChain::FindFork(const CBlockLocator &locator) const {
return Genesis();
}
-//////////////////////////////////////////////////////////////////////////////
-//
-// CCoinsView implementations
-//
-
-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; }
-CBlockIndex *CCoinsView::GetBestBlock() { return NULL; }
-bool CCoinsView::SetBestBlock(CBlockIndex *pindex) { return false; }
-bool CCoinsView::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) { 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); }
-CBlockIndex *CCoinsViewBacked::GetBestBlock() { return base->GetBestBlock(); }
-bool CCoinsViewBacked::SetBestBlock(CBlockIndex *pindex) { return base->SetBestBlock(pindex); }
-void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
-bool CCoinsViewBacked::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) { return base->BatchWrite(mapCoins, pindex); }
-bool CCoinsViewBacked::GetStats(CCoinsStats &stats) { return base->GetStats(stats); }
-
-CCoinsViewCache::CCoinsViewCache(CCoinsView &baseIn, bool fDummy) : CCoinsViewBacked(baseIn), pindexTip(NULL) { }
-
-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();
-}
-
-CBlockIndex *CCoinsViewCache::GetBestBlock() {
- if (pindexTip == NULL)
- pindexTip = base->GetBestBlock();
- return pindexTip;
-}
-
-bool CCoinsViewCache::SetBestBlock(CBlockIndex *pindex) {
- pindexTip = pindex;
- return true;
-}
-
-bool CCoinsViewCache::BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex) {
- for (std::map<uint256, CCoins>::const_iterator it = mapCoins.begin(); it != mapCoins.end(); it++)
- cacheCoins[it->first] = it->second;
- pindexTip = pindex;
- return true;
-}
-
-bool CCoinsViewCache::Flush() {
- bool fOk = base->BatchWrite(cacheCoins, pindexTip);
- if (fOk)
- cacheCoins.clear();
- return fOk;
-}
-
-unsigned int CCoinsViewCache::GetCacheSize() {
- return cacheCoins.size();
-}
-
-/** Helper; lookup from tip (used calling mempool.check()
- NOTE: code calling this MUST hold the cs_main lock so
- another thread doesn't modify pcoinsTip. When we switch
- to C++11 this should be replaced by lambda expressions...
- **/
-static CCoins &LookupFromTip(const uint256& hash) {
- return pcoinsTip->GetCoins(hash);
-}
-
-/** CCoinsView that brings transactions from a memorypool into view.
- It does not check for spendings by memory pool transactions. */
-CCoinsViewMemPool::CCoinsViewMemPool(CCoinsView &baseIn, CTxMemPool &mempoolIn) : CCoinsViewBacked(baseIn), mempool(mempoolIn) { }
-
-bool CCoinsViewMemPool::GetCoins(const uint256 &txid, CCoins &coins) {
- if (base->GetCoins(txid, coins))
- return true;
- CTransaction tx;
- if (mempool.lookup(txid, tx)) {
- coins = CCoins(tx, MEMPOOL_HEIGHT);
- return true;
- }
- return false;
-}
-
-bool CCoinsViewMemPool::HaveCoins(const uint256 &txid) {
- return mempool.exists(txid) || base->HaveCoins(txid);
-}
-
CCoinsViewCache *pcoinsTip = NULL;
CBlockTreeDB *pblocktree = NULL;
@@ -1430,25 +1308,6 @@ void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev)
-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;
-}
-
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight, const uint256 &txhash)
{
// mark inputs spent
@@ -1465,27 +1324,6 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
assert(inputs.SetCoins(txhash, CCoins(tx, nHeight)));
}
-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;
-}
-
bool CScriptCheck::operator()() const {
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
if (!VerifyScript(scriptSig, scriptPubKey, *ptxTo, nIn, nFlags, nHashType))
@@ -1512,7 +1350,8 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach
// While checking, GetBestBlock() refers to the parent block.
// This is also true for mempool checks.
- int nSpendHeight = inputs.GetBestBlock()->nHeight + 1;
+ CBlockIndex *pindexPrev = mapBlockIndex.find(inputs.GetBestBlock())->second;
+ int nSpendHeight = pindexPrev->nHeight + 1;
int64_t nValueIn = 0;
int64_t nFees = 0;
for (unsigned int i = 0; i < tx.vin.size(); i++)
@@ -1588,7 +1427,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach
bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean)
{
- assert(pindex == view.GetBestBlock());
+ assert(pindex->GetBlockHash() == view.GetBestBlock());
if (pfClean)
*pfClean = false;
@@ -1664,7 +1503,7 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
}
// move best block pointer to prevout block
- view.SetBestBlock(pindex->pprev);
+ view.SetBestBlock(pindex->pprev->GetBlockHash());
if (pfClean) {
*pfClean = fClean;
@@ -1713,12 +1552,13 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
return false;
// verify that the view's current state corresponds to the previous block
- assert(pindex->pprev == view.GetBestBlock());
+ uint256 hashPrevBlock = pindex->pprev == NULL ? uint256(0) : pindex->pprev->GetBlockHash();
+ assert(hashPrevBlock == view.GetBestBlock());
// Special case for the genesis block, skipping connection of its transactions
// (its coinbase is unspendable)
if (block.GetHash() == Params().HashGenesisBlock()) {
- view.SetBestBlock(pindex);
+ view.SetBestBlock(pindex->GetBlockHash());
return true;
}
@@ -1855,7 +1695,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
return state.Abort(_("Failed to write transaction index"));
// add this block to the view's block chain
- assert(view.SetBestBlock(pindex));
+ assert(view.SetBestBlock(pindex->GetBlockHash()));
// Watch for transactions paying to me
for (unsigned int i = 0; i < block.vtx.size(); i++)
@@ -1866,14 +1706,16 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
{
- mempool.check(&LookupFromTip);
+ mempool.check(pcoinsTip);
// All modifications to the coin state will be done in this cache.
// Only when all have succeeded, we push it to pcoinsTip.
CCoinsViewCache view(*pcoinsTip, true);
// Find the fork (typically, there is none)
- CBlockIndex* pfork = view.GetBestBlock();
+ std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(view.GetBestBlock());
+ CBlockIndex* ptip = (it != mapBlockIndex.end()) ? it->second : NULL;
+ CBlockIndex* pfork = ptip;
CBlockIndex* plonger = pindexNew;
while (pfork && pfork != plonger)
{
@@ -1889,7 +1731,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
// List of what to disconnect (typically nothing)
vector<CBlockIndex*> vDisconnect;
- for (CBlockIndex* pindex = view.GetBestBlock(); pindex != pfork; pindex = pindex->pprev)
+ for (CBlockIndex* pindex = ptip; pindex != pfork; pindex = pindex->pprev)
vDisconnect.push_back(pindex);
// List of what to connect (typically only pindexNew)
@@ -1989,7 +1831,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
mempool.removeConflicts(tx);
}
- mempool.check(&LookupFromTip);
+ mempool.check(pcoinsTip);
// Update best block in wallet (so we can detect restored wallets)
if ((pindexNew->nHeight % 20160) == 0 || (!fIsInitialDownload && (pindexNew->nHeight % 144) == 0))
@@ -2730,9 +2572,10 @@ bool static LoadBlockIndexDB()
LogPrintf("LoadBlockIndexDB(): transaction index %s\n", fTxIndex ? "enabled" : "disabled");
// Load pointer to end of best chain
- chainActive.SetTip(pcoinsTip->GetBestBlock());
- if (chainActive.Tip() == NULL)
+ std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
+ if (it == mapBlockIndex.end())
return true;
+ chainActive.SetTip(it->second);
LogPrintf("LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s\n",
chainActive.Tip()->GetBlockHash().ToString().c_str(), chainActive.Height(),
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()).c_str());
@@ -3580,7 +3423,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CValidationState state;
if (AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs))
{
- mempool.check(&LookupFromTip);
+ mempool.check(pcoinsTip);
RelayTransaction(tx, inv.hash);
mapAlreadyAskedFor.erase(inv);
vWorkQueue.push_back(inv.hash);
@@ -3616,7 +3459,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vEraseQueue.push_back(orphanHash);
LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString().c_str());
}
- mempool.check(&LookupFromTip);
+ mempool.check(pcoinsTip);
}
}