diff --git a/src/chain.h b/src/chain.h --- a/src/chain.h +++ b/src/chain.h @@ -13,6 +13,7 @@ #include "diskblockpos.h" #include "pow.h" #include "primitives/block.h" +#include "sync.h" #include "tinyformat.h" #include "uint256.h" @@ -240,6 +241,13 @@ typedef std::unordered_map BlockMap; extern BlockMap &mapBlockIndex; +extern CCriticalSection cs_main; + +inline CBlockIndex *LookupBlockIndex(const uint256 &hash) { + AssertLockHeld(cs_main); + BlockMap::const_iterator it = mapBlockIndex.find(hash); + return it == mapBlockIndex.end() ? nullptr : it->second; +} arith_uint256 GetBlockProof(const CBlockIndex &block); diff --git a/src/checkpoints.h b/src/checkpoints.h --- a/src/checkpoints.h +++ b/src/checkpoints.h @@ -21,7 +21,7 @@ //! Returns true if block passes checkpoint checks bool CheckBlock(const CCheckpointData &data, int nHeight, const uint256 &hash); -//! Returns last CBlockIndex* in mapBlockIndex that is a checkpoint +//! Returns last CBlockIndex* that is a checkpoint CBlockIndex *GetLastCheckpoint(const CCheckpointData &data); } // namespace Checkpoints diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -27,9 +27,9 @@ for (const MapCheckpoints::value_type &i : reverse_iterate(checkpoints)) { const uint256 &hash = i.second; - BlockMap::const_iterator t = mapBlockIndex.find(hash); - if (t != mapBlockIndex.end()) { - return t->second; + CBlockIndex *pindex = LookupBlockIndex(hash); + if (pindex) { + return pindex; } } diff --git a/src/init.cpp b/src/init.cpp --- a/src/init.cpp +++ b/src/init.cpp @@ -2043,6 +2043,8 @@ uiInterface.InitMessage(_("Loading block index...")); + LOCK(cs_main); + nStart = GetTimeMillis(); do { try { @@ -2078,8 +2080,8 @@ // (we're likely using a testnet datadir, or the other way // around). if (!mapBlockIndex.empty() && - mapBlockIndex.count( - chainparams.GetConsensus().hashGenesisBlock) == 0) { + !LookupBlockIndex( + chainparams.GetConsensus().hashGenesisBlock)) { return InitError(_("Incorrect or no genesis block found. " "Wrong datadir for network?")); } @@ -2174,21 +2176,17 @@ MIN_BLOCKS_TO_KEEP); } - { - LOCK(cs_main); - CBlockIndex *tip = chainActive.Tip(); - RPCNotifyBlockChange(true, tip); - if (tip && tip->nTime > GetAdjustedTime() + - MAX_FUTURE_BLOCK_TIME) { - strLoadError = - _("The block database contains a block which " - "appears to be from the future. This may be " - "due to your computer's date and time being " - "set incorrectly. Only rebuild the block " - "database if you are sure that your " - "computer's date and time are correct"); - break; - } + CBlockIndex *tip = chainActive.Tip(); + RPCNotifyBlockChange(true, tip); + if (tip && tip->nTime > + GetAdjustedTime() + MAX_FUTURE_BLOCK_TIME) { + strLoadError = _( + "The block database contains a block which appears " + "to be from the future. This may be due to your " + "computer's date and time being set incorrectly. " + "Only rebuild the block database if you are sure " + "that your computer's date and time are correct"); + break; } if (!CVerifyDB().VerifyDB( diff --git a/src/net_processing.cpp b/src/net_processing.cpp --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -439,13 +439,12 @@ assert(state != nullptr); if (!state->hashLastUnknownBlock.IsNull()) { - BlockMap::iterator itOld = - mapBlockIndex.find(state->hashLastUnknownBlock); - if (itOld != mapBlockIndex.end() && itOld->second->nChainWork > 0) { + const CBlockIndex *pindex = + LookupBlockIndex(state->hashLastUnknownBlock); + if (pindex && pindex->nChainWork > 0) { if (state->pindexBestKnownBlock == nullptr || - itOld->second->nChainWork >= - state->pindexBestKnownBlock->nChainWork) { - state->pindexBestKnownBlock = itOld->second; + pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) { + state->pindexBestKnownBlock = pindex; } state->hashLastUnknownBlock.SetNull(); } @@ -460,12 +459,12 @@ ProcessBlockAvailability(nodeid); - BlockMap::iterator it = mapBlockIndex.find(hash); - if (it != mapBlockIndex.end() && it->second->nChainWork > 0) { + const CBlockIndex *pindex = LookupBlockIndex(hash); + if (pindex && pindex->nChainWork > 0) { // An actually better block was announced. if (state->pindexBestKnownBlock == nullptr || - it->second->nChainWork >= state->pindexBestKnownBlock->nChainWork) { - state->pindexBestKnownBlock = it->second; + pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) { + state->pindexBestKnownBlock = pindex; } } else { // An unknown block was announced; just assume that the latest one is @@ -1191,7 +1190,7 @@ pcoinsTip->HaveCoinInCache(COutPoint(inv.hash, 1)); } case MSG_BLOCK: - return mapBlockIndex.count(inv.hash); + return LookupBlockIndex(inv.hash) != nullptr; } // Don't know what it is, just say we already got one return true; @@ -1263,11 +1262,10 @@ bool need_activate_chain = false; { LOCK(cs_main); - BlockMap::iterator mi = mapBlockIndex.find(inv.hash); - if (mi != mapBlockIndex.end()) { - if (mi->second->nChainTx && - !mi->second->IsValid(BlockValidity::SCRIPTS) && - mi->second->IsValid(BlockValidity::TREE)) { + const CBlockIndex *pindex = LookupBlockIndex(inv.hash); + if (pindex) { + if (pindex->nChainTx && !pindex->IsValid(BlockValidity::SCRIPTS) && + pindex->IsValid(BlockValidity::TREE)) { // If we have the block and all of its parents, but have not yet // validated it, we might be in the middle of connecting it (ie // in the unlock of cs_main before ActivateBestChain but after @@ -1283,9 +1281,9 @@ } LOCK(cs_main); - BlockMap::iterator mi = mapBlockIndex.find(inv.hash); - if (mi != mapBlockIndex.end()) { - send = BlockRequestAllowed(mi->second, consensusParams); + const CBlockIndex *pindex = LookupBlockIndex(inv.hash); + if (pindex) { + send = BlockRequestAllowed(pindex, consensusParams); if (!send) { LogPrint(BCLog::NET, "%s: ignoring request from peer=%i for old " @@ -1299,7 +1297,7 @@ // Never disconnect whitelisted nodes. if (send && connman->OutboundTargetReached(true) && (((pindexBestHeader != nullptr) && - (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() > + (pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.type == MSG_FILTERED_BLOCK) && !pfrom->fWhitelisted) { @@ -1319,7 +1317,7 @@ ((((pfrom->GetLocalServices() & NODE_NETWORK_LIMITED) == NODE_NETWORK_LIMITED) && ((pfrom->GetLocalServices() & NODE_NETWORK) != NODE_NETWORK) && - (chainActive.Tip()->nHeight - mi->second->nHeight > + (chainActive.Tip()->nHeight - pindex->nHeight > (int)NODE_NETWORK_LIMITED_MIN_BLOCKS + 2)))) { LogPrint(BCLog::NET, "Ignore block request below NODE_NETWORK_LIMITED " @@ -1333,16 +1331,17 @@ } // Pruned nodes may have deleted the block, so check whether it's available // before trying to send. - if (send && (mi->second->nStatus.hasData())) { + if (send && pindex->nStatus.hasData()) { std::shared_ptr pblock; if (a_recent_block && - a_recent_block->GetHash() == (*mi).second->GetBlockHash()) { + a_recent_block->GetHash() == pindex->GetBlockHash()) { pblock = a_recent_block; } else { // Send block from disk std::shared_ptr pblockRead = std::make_shared(); - if (!ReadBlockFromDisk(*pblockRead, (*mi).second, config)) + if (!ReadBlockFromDisk(*pblockRead, pindex, config)) { assert(!"cannot load block from disk"); + } pblock = pblockRead; } if (inv.type == MSG_BLOCK) { @@ -1386,7 +1385,7 @@ // we respond with the full, non-compact block. int nSendFlags = 0; if (CanDirectFetch(consensusParams) && - mi->second->nHeight >= + pindex->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) { CBlockHeaderAndShortTxIDs cmpctblock(*pblock); connman->PushMessage( @@ -1540,8 +1539,7 @@ // don't connect before giving DoS points // - Once a headers message is received that is valid and does connect, // nUnconnectingHeaders gets reset back to 0. - if (mapBlockIndex.find(headers[0].hashPrevBlock) == - mapBlockIndex.end() && + if (!LookupBlockIndex(headers[0].hashPrevBlock) && nCount < MAX_BLOCKS_TO_ANNOUNCE) { nodestate->nUnconnectingHeaders++; connman->PushMessage( @@ -1580,7 +1578,7 @@ // If we don't have the last header, then they'll have given us // something new (if these headers are valid). - if (mapBlockIndex.find(hashLastBlock) == mapBlockIndex.end()) { + if (!LookupBlockIndex(hashLastBlock)) { received_new_header = true; } } @@ -1596,8 +1594,7 @@ Misbehaving(pfrom, nDoS, state.GetRejectReason()); } if (punish_duplicate_invalid && - mapBlockIndex.find(first_invalid_header.GetHash()) != - mapBlockIndex.end()) { + LookupBlockIndex(first_invalid_header.GetHash())) { // Goal: don't allow outbound peers to use up our outbound // connection slots if they are on incompatible chains. // @@ -2359,15 +2356,15 @@ LOCK(cs_main); - BlockMap::iterator it = mapBlockIndex.find(req.blockhash); - if (it == mapBlockIndex.end() || !it->second->nStatus.hasData()) { + const CBlockIndex *pindex = LookupBlockIndex(req.blockhash); + if (!pindex || !pindex->nStatus.hasData()) { LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block we don't have", pfrom->GetId()); return true; } - if (it->second->nHeight < chainActive.Height() - MAX_BLOCKTXN_DEPTH) { + if (pindex->nHeight < chainActive.Height() - MAX_BLOCKTXN_DEPTH) { // If an older block is requested (should never happen in practice, // but can happen in tests) send a block response instead of a // blocktxn response. Sending a full block response instead of a @@ -2388,7 +2385,7 @@ } CBlock block; - bool ret = ReadBlockFromDisk(block, it->second, config); + bool ret = ReadBlockFromDisk(block, pindex, config); assert(ret); SendBlockTransactions(block, req, pfrom, connman); @@ -2412,11 +2409,10 @@ const CBlockIndex *pindex = nullptr; if (locator.IsNull()) { // If locator is null, return the hashStop block - BlockMap::iterator mi = mapBlockIndex.find(hashStop); - if (mi == mapBlockIndex.end()) { + pindex = LookupBlockIndex(hashStop); + if (!pindex) { return true; } - pindex = (*mi).second; if (!BlockRequestAllowed(pindex, chainparams.GetConsensus())) { LogPrint(BCLog::NET, @@ -2693,8 +2689,7 @@ { LOCK(cs_main); - if (mapBlockIndex.find(cmpctblock.header.hashPrevBlock) == - mapBlockIndex.end()) { + if (!LookupBlockIndex(cmpctblock.header.hashPrevBlock)) { // Doesn't connect (or is genesis), instead of DoSing in // AcceptBlockHeader, request deeper headers if (!IsInitialBlockDownload()) { @@ -2707,8 +2702,7 @@ return true; } - if (mapBlockIndex.find(cmpctblock.header.GetHash()) == - mapBlockIndex.end()) { + if (!LookupBlockIndex(cmpctblock.header.GetHash())) { received_new_header = true; } } @@ -3880,9 +3874,8 @@ // send all headers past that one. If we come across an headers that // aren't on chainActive, give up. for (const uint256 &hash : pto->vBlockHashesToAnnounce) { - BlockMap::iterator mi = mapBlockIndex.find(hash); - assert(mi != mapBlockIndex.end()); - const CBlockIndex *pindex = mi->second; + const CBlockIndex *pindex = LookupBlockIndex(hash); + assert(pindex); if (chainActive[pindex->nHeight] != pindex) { // Bail out if we reorged away from this block fRevertToInv = true; @@ -3984,9 +3977,8 @@ if (!pto->vBlockHashesToAnnounce.empty()) { const uint256 &hashToAnnounce = pto->vBlockHashesToAnnounce.back(); - BlockMap::iterator mi = mapBlockIndex.find(hashToAnnounce); - assert(mi != mapBlockIndex.end()); - const CBlockIndex *pindex = mi->second; + const CBlockIndex *pindex = LookupBlockIndex(hashToAnnounce); + assert(pindex); // Warn if we're announcing a block that is not on the main // chain. This should be very rare and could be optimized out. diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -160,11 +160,7 @@ // Determine transaction status // Find the block the tx is in - CBlockIndex *pindex = nullptr; - BlockMap::iterator mi = mapBlockIndex.find(wtx.hashBlock); - if (mi != mapBlockIndex.end()) { - pindex = (*mi).second; - } + const CBlockIndex *pindex = LookupBlockIndex(wtx.hashBlock); // Sort order, unrecorded transactions sort to the top status.sortKey = diff --git a/src/rest.cpp b/src/rest.cpp --- a/src/rest.cpp +++ b/src/rest.cpp @@ -164,9 +164,7 @@ headers.reserve(count); { LOCK(cs_main); - BlockMap::const_iterator it = mapBlockIndex.find(hash); - const CBlockIndex *pindex = - (it != mapBlockIndex.end()) ? it->second : nullptr; + const CBlockIndex *pindex = LookupBlockIndex(hash); while (pindex != nullptr && chainActive.Contains(pindex)) { headers.push_back(pindex); if (headers.size() == size_t(count)) { @@ -238,11 +236,11 @@ CBlockIndex *pblockindex = nullptr; { LOCK(cs_main); - if (mapBlockIndex.count(hash) == 0) { + pblockindex = LookupBlockIndex(hash); + if (!pblockindex) { return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found"); } - pblockindex = mapBlockIndex[hash]; if (fHavePruned && !pblockindex->nStatus.hasData() && pblockindex->nTx > 0) { return RESTERR(req, HTTP_NOT_FOUND, diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -762,12 +762,11 @@ fVerbose = request.params[1].get_bool(); } - if (mapBlockIndex.count(hash) == 0) { + const CBlockIndex *pblockindex = LookupBlockIndex(hash); + if (!pblockindex) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } - CBlockIndex *pblockindex = mapBlockIndex[hash]; - if (!fVerbose) { CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); ssBlock << pblockindex->GetBlockHeader(); @@ -858,13 +857,12 @@ } } - if (mapBlockIndex.count(hash) == 0) { + const CBlockIndex *pblockindex = LookupBlockIndex(hash); + if (!pblockindex) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } CBlock block; - CBlockIndex *pblockindex = mapBlockIndex[hash]; - if (fHavePruned && !pblockindex->nStatus.hasData() && pblockindex->nTx > 0) { throw JSONRPCError(RPC_MISC_ERROR, "Block not available (pruned data)"); @@ -933,7 +931,7 @@ stats.hashBlock = pcursor->GetBestBlock(); { LOCK(cs_main); - stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight; + stats.nHeight = LookupBlockIndex(stats.hashBlock)->nHeight; } ss << stats.hashBlock; uint256 prevkey; @@ -1141,8 +1139,7 @@ } } - BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); - CBlockIndex *pindex = it->second; + const CBlockIndex *pindex = LookupBlockIndex(pcoinsTip->GetBestBlock()); ret.pushKV("bestblock", pindex->GetBlockHash().GetHex()); if (coin.GetHeight() == MEMPOOL_HEIGHT) { ret.pushKV("confirmations", 0); @@ -1524,11 +1521,10 @@ { LOCK(cs_main); - if (mapBlockIndex.count(hash) == 0) { + pblockindex = LookupBlockIndex(hash); + if (!pblockindex) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } - - pblockindex = mapBlockIndex[hash]; } CValidationState state; @@ -1562,11 +1558,11 @@ { LOCK(cs_main); - if (mapBlockIndex.count(hash) == 0) { + CBlockIndex *pblockindex = LookupBlockIndex(hash); + if (!pblockindex) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } - CBlockIndex *pblockindex = mapBlockIndex[hash]; FinalizeBlockAndInvalidate(config, state, pblockindex); } @@ -1602,11 +1598,11 @@ { LOCK(cs_main); - if (mapBlockIndex.count(hash) == 0) { + CBlockIndex *pblockindex = LookupBlockIndex(hash); + if (!pblockindex) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } - CBlockIndex *pblockindex = mapBlockIndex[hash]; InvalidateBlock(config, state, pblockindex); } @@ -1680,11 +1676,11 @@ { LOCK(cs_main); - if (mapBlockIndex.count(hash) == 0) { + CBlockIndex *pblockindex = LookupBlockIndex(hash); + if (!pblockindex) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } - CBlockIndex *pblockindex = mapBlockIndex[hash]; ResetBlockFailureFlags(pblockindex); } @@ -1785,11 +1781,10 @@ } else { uint256 hash = uint256S(request.params[1].get_str()); LOCK(cs_main); - auto it = mapBlockIndex.find(hash); - if (it == mapBlockIndex.end()) { + pindex = LookupBlockIndex(hash); + if (!pindex) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } - pindex = it->second; if (!chainActive.Contains(pindex)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Block is not in main chain"); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -480,9 +480,8 @@ } uint256 hash = block.GetHash(); - BlockMap::iterator mi = mapBlockIndex.find(hash); - if (mi != mapBlockIndex.end()) { - CBlockIndex *pindex = mi->second; + const CBlockIndex *pindex = LookupBlockIndex(hash); + if (pindex) { if (pindex->IsValid(BlockValidity::SCRIPTS)) { return "duplicate"; } @@ -736,9 +735,8 @@ bool fBlockPresent = false; { LOCK(cs_main); - BlockMap::iterator mi = mapBlockIndex.find(hash); - if (mi != mapBlockIndex.end()) { - CBlockIndex *pindex = mi->second; + const CBlockIndex *pindex = LookupBlockIndex(hash); + if (pindex) { if (pindex->IsValid(BlockValidity::SCRIPTS)) { return "duplicate"; } diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -47,9 +47,8 @@ if (!hashBlock.IsNull()) { entry.pushKV("blockhash", hashBlock.GetHex()); - BlockMap::iterator mi = mapBlockIndex.find(hashBlock); - if (mi != mapBlockIndex.end() && (*mi).second) { - CBlockIndex *pindex = (*mi).second; + CBlockIndex *pindex = LookupBlockIndex(hashBlock); + if (pindex) { if (chainActive.Contains(pindex)) { entry.pushKV("confirmations", 1 + chainActive.Height() - pindex->nHeight); @@ -180,12 +179,11 @@ if (!request.params[2].isNull()) { uint256 blockhash = ParseHashV(request.params[2], "parameter 3"); - BlockMap::iterator it = mapBlockIndex.find(blockhash); - if (it == mapBlockIndex.end()) { + blockindex = LookupBlockIndex(blockhash); + if (!blockindex) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block hash not found"); } - blockindex = it->second; in_active_chain = chainActive.Contains(blockindex); } @@ -278,10 +276,10 @@ uint256 hashBlock; if (!request.params[1].isNull()) { hashBlock = uint256S(request.params[1].get_str()); - if (!mapBlockIndex.count(hashBlock)) { + pblockindex = LookupBlockIndex(hashBlock); + if (!pblockindex) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } - pblockindex = mapBlockIndex[hashBlock]; } else { // Loop through txids and try to find which block they're in. Exit loop // once a block is found. @@ -302,11 +300,10 @@ "Transaction not yet in block"); } - if (!mapBlockIndex.count(hashBlock)) { + pblockindex = LookupBlockIndex(hashBlock); + if (!pblockindex) { throw JSONRPCError(RPC_INTERNAL_ERROR, "Transaction index corrupt"); } - - pblockindex = mapBlockIndex[hashBlock]; } CBlock block; @@ -366,8 +363,8 @@ LOCK(cs_main); - if (!mapBlockIndex.count(merkleBlock.header.GetHash()) || - !chainActive.Contains(mapBlockIndex[merkleBlock.header.GetHash()])) { + const CBlockIndex *pindex = LookupBlockIndex(merkleBlock.header.GetHash()); + if (!pindex || !chainActive.Contains(pindex)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain"); } diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -251,11 +251,12 @@ CBlockIndex *FindForkInGlobalIndex(const CChain &chain, const CBlockLocator &locator) { + AssertLockHeld(cs_main); + // Find the first block the caller has in the main chain for (const uint256 &hash : locator.vHave) { - BlockMap::iterator mi = mapBlockIndex.find(hash); - if (mi != mapBlockIndex.end()) { - CBlockIndex *pindex = (*mi).second; + CBlockIndex *pindex = LookupBlockIndex(hash); + if (pindex) { if (chain.Contains(pindex)) { return pindex; } @@ -1209,7 +1210,7 @@ int GetSpendHeight(const CCoinsViewCache &inputs) { LOCK(cs_main); - CBlockIndex *pindexPrev = mapBlockIndex.find(inputs.GetBestBlock())->second; + CBlockIndex *pindexPrev = LookupBlockIndex(inputs.GetBestBlock()); return pindexPrev->nHeight + 1; } @@ -3269,6 +3270,8 @@ } CBlockIndex *CChainState::AddToBlockIndex(const CBlockHeader &block) { + AssertLockHeld(cs_main); + // Check for duplicate uint256 hash = block.GetHash(); BlockMap::iterator it = mapBlockIndex.find(hash); @@ -4406,6 +4409,8 @@ } CBlockIndex *CChainState::InsertBlockIndex(const uint256 &hash) { + AssertLockHeld(cs_main); + if (hash.IsNull()) { return nullptr; } @@ -4563,6 +4568,8 @@ } bool LoadChainTip(const Config &config) { + AssertLockHeld(cs_main); + if (chainActive.Tip() && chainActive.Tip()->GetBlockHash() == pcoinsTip->GetBestBlock()) { return true; @@ -4579,12 +4586,11 @@ } // Load pointer to end of best chain - BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); - if (it == mapBlockIndex.end()) { + CBlockIndex *pindex = LookupBlockIndex(pcoinsTip->GetBestBlock()); + if (!pindex) { return false; } - - chainActive.SetTip(it->second); + chainActive.SetTip(pindex); g_chainstate.PruneBlockIndexCandidates(); @@ -5119,42 +5125,43 @@ blkdat >> block; nRewind = blkdat.GetPos(); - // detect out of order blocks, and store them for later uint256 hash = block.GetHash(); - if (hash != chainparams.GetConsensus().hashGenesisBlock && - mapBlockIndex.find(block.hashPrevBlock) == - mapBlockIndex.end()) { - LogPrint(BCLog::REINDEX, - "%s: Out of order block %s, parent %s not known\n", - __func__, hash.ToString(), - block.hashPrevBlock.ToString()); - if (dbp) { - mapBlocksUnknownParent.insert( - std::make_pair(block.hashPrevBlock, *dbp)); - } - continue; - } - - // process in case the block isn't known yet - if (mapBlockIndex.count(hash) == 0 || - !mapBlockIndex[hash]->nStatus.hasData()) { + { LOCK(cs_main); - CValidationState state; - if (g_chainstate.AcceptBlock(config, pblock, state, true, - dbp, nullptr)) { - nLoaded++; + // detect out of order blocks, and store them for later + if (hash != chainparams.GetConsensus().hashGenesisBlock && + !LookupBlockIndex(block.hashPrevBlock)) { + LogPrint( + BCLog::REINDEX, + "%s: Out of order block %s, parent %s not known\n", + __func__, hash.ToString(), + block.hashPrevBlock.ToString()); + if (dbp) { + mapBlocksUnknownParent.insert( + std::make_pair(block.hashPrevBlock, *dbp)); + } + continue; } - if (state.IsError()) { - break; + // process in case the block isn't known yet + CBlockIndex *pindex = LookupBlockIndex(hash); + if (!pindex || !pindex->nStatus.hasData()) { + CValidationState state; + if (g_chainstate.AcceptBlock(config, pblock, state, + true, dbp, nullptr)) { + nLoaded++; + } + if (state.IsError()) { + break; + } + } else if (hash != chainparams.GetConsensus() + .hashGenesisBlock && + pindex->nHeight % 1000 == 0) { + LogPrint( + BCLog::REINDEX, + "Block Import: already had block %s at height %d\n", + hash.ToString(), pindex->nHeight); } - } else if (hash != - chainparams.GetConsensus().hashGenesisBlock && - mapBlockIndex[hash]->nHeight % 1000 == 0) { - LogPrint( - BCLog::REINDEX, - "Block Import: already had block %s at height %d\n", - hash.ToString(), mapBlockIndex[hash]->nHeight); } // Activate the genesis block so normal node progress can diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -366,10 +366,9 @@ merkleBlock.header.hashMerkleRoot) { LOCK(cs_main); - - if (!mapBlockIndex.count(merkleBlock.header.GetHash()) || - !chainActive.Contains( - mapBlockIndex[merkleBlock.header.GetHash()])) { + const CBlockIndex *pindex = + LookupBlockIndex(merkleBlock.header.GetHash()); + if (!pindex || !chainActive.Contains(pindex)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found in chain"); } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -115,7 +115,8 @@ if (confirms > 0) { entry.pushKV("blockhash", wtx.hashBlock.GetHex()); entry.pushKV("blockindex", wtx.nIndex); - entry.pushKV("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()); + entry.pushKV("blocktime", + LookupBlockIndex(wtx.hashBlock)->GetBlockTime()); } else { entry.pushKV("trusted", wtx.IsTrusted()); } @@ -2242,11 +2243,10 @@ uint256 blockId; blockId.SetHex(request.params[0].get_str()); - BlockMap::iterator it = mapBlockIndex.find(blockId); - if (it == mapBlockIndex.end()) { + paltindex = pindex = LookupBlockIndex(blockId); + if (!pindex) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); } - paltindex = pindex = it->second; if (chainActive[pindex->nHeight] != pindex) { // the block being asked for is a part of a deactivated chain; // we don't want to depend on its perceived height in the block diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1200,11 +1200,9 @@ LOCK2(cs_main, cs_wallet); int conflictconfirms = 0; - if (mapBlockIndex.count(hashBlock)) { - CBlockIndex *pindex = mapBlockIndex[hashBlock]; - if (chainActive.Contains(pindex)) { - conflictconfirms = -(chainActive.Height() - pindex->nHeight + 1); - } + CBlockIndex *pindex = LookupBlockIndex(hashBlock); + if (pindex && chainActive.Contains(pindex)) { + conflictconfirms = -(chainActive.Height() - pindex->nHeight + 1); } // If number of conflict confirms cannot be determined, this means that the @@ -4005,10 +4003,10 @@ for (const auto &entry : mapWallet) { // iterate over all wallet transactions... const CWalletTx &wtx = entry.second; - BlockMap::const_iterator blit = mapBlockIndex.find(wtx.hashBlock); - if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) { - // ... which are already in a block. - int nHeight = blit->second->nHeight; + CBlockIndex *pindex = LookupBlockIndex(wtx.hashBlock); + if (pindex && chainActive.Contains(pindex)) { + // ... which are already in a block + int nHeight = pindex->nHeight; for (const CTxOut &txout : wtx.tx->vout) { // Iterate over all their outputs... CAffectedKeysVisitor(*this, vAffected) @@ -4019,7 +4017,7 @@ mapKeyFirstBlock.find(keyid); if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight) { - rit->second = blit->second; + rit->second = pindex; } } vAffected.clear(); @@ -4059,7 +4057,12 @@ unsigned int CWallet::ComputeTimeSmart(const CWalletTx &wtx) const { unsigned int nTimeSmart = wtx.nTimeReceived; if (!wtx.hashUnset()) { - if (mapBlockIndex.count(wtx.hashBlock)) { + const CBlockIndex *pindex = nullptr; + { + LOCK(cs_main); + pindex = LookupBlockIndex(wtx.hashBlock); + } + if (pindex) { int64_t latestNow = wtx.nTimeReceived; int64_t latestEntry = 0; @@ -4091,7 +4094,7 @@ } } - int64_t blocktime = mapBlockIndex[wtx.hashBlock]->GetBlockTime(); + int64_t blocktime = pindex->GetBlockTime(); nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow)); } else { LogPrintf("%s: found %s in block %s not in index\n", __func__, @@ -4281,6 +4284,8 @@ // Try to top up keypool. No-op if the wallet is locked. walletInstance->TopUpKeyPool(); + LOCK(cs_main); + CBlockIndex *pindexRescan = chainActive.Genesis(); if (!gArgs.GetBoolArg("-rescan", false)) { CWalletDB walletdb(*walletInstance->dbw); @@ -4423,12 +4428,7 @@ AssertLockHeld(cs_main); // Find the block it claims to be in. - BlockMap::iterator mi = mapBlockIndex.find(hashBlock); - if (mi == mapBlockIndex.end()) { - return 0; - } - - CBlockIndex *pindex = (*mi).second; + CBlockIndex *pindex = LookupBlockIndex(hashBlock); if (!pindex || !chainActive.Contains(pindex)) { return 0; }