diff options
author | Gavin Andresen <gavinandresen@gmail.com> | 2013-11-10 18:09:58 -0800 |
---|---|---|
committer | Gavin Andresen <gavinandresen@gmail.com> | 2013-11-10 18:09:58 -0800 |
commit | 7d7df381f85112f5d00dc8f164451dea5baa48bb (patch) | |
tree | 624d282fc308688102fa17c1fd331e99e9ac0720 /src/main.cpp | |
parent | 16d5f2c5e0a7276fb2b09d8dd51b7bac2753c4cc (diff) | |
parent | a0fa20a12b69717636050dd8742713b1d82ae524 (diff) |
Merge pull request #3199 from sipa/mempoolmove
Cleanup refactoring of coins/mempool
Diffstat (limited to 'src/main.cpp')
-rw-r--r-- | src/main.cpp | 195 |
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); } } |