From 0efc03deb0fe2dad1855997c2f36f27dfc6fc539 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 13 Mar 2018 19:04:28 +0100 Subject: [PATCH] Merge bitcoin#11041 Add LookupBlockIndex Contains both the changes done upstream and changes done in Dash codebase Signed-off-by: pasta --- src/checkpoints.cpp | 7 ++- src/checkpoints.h | 2 +- src/evo/simplifiedmns.cpp | 11 ++-- src/governance/governance-object.cpp | 9 +-- src/init.cpp | 22 +++---- src/llmq/quorums.cpp | 5 +- src/llmq/quorums_blockprocessor.cpp | 8 +-- src/llmq/quorums_chainlocks.cpp | 19 +++--- src/llmq/quorums_commitment.cpp | 4 +- src/llmq/quorums_debug.cpp | 5 +- src/llmq/quorums_dkgsessionhandler.cpp | 2 +- src/llmq/quorums_instantsend.cpp | 6 +- src/net_processing.cpp | 83 +++++++++++++------------- src/node/coinstats.cpp | 3 +- src/rest.cpp | 8 +-- src/rpc/blockchain.cpp | 35 +++++------ src/rpc/mining.cpp | 10 ++-- src/rpc/rawtransaction.cpp | 24 ++++---- src/validation.cpp | 65 +++++++++++--------- src/validation.h | 7 +++ src/wallet/rpcdump.cpp | 5 +- src/wallet/rpcwallet.cpp | 7 +-- src/wallet/wallet.cpp | 55 ++++++++--------- 23 files changed, 202 insertions(+), 200 deletions(-) diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 1925925607..066dcb32b6 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -22,9 +22,10 @@ namespace Checkpoints { 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; + } } return nullptr; } diff --git a/src/checkpoints.h b/src/checkpoints.h index 7697b96931..032836a8f7 100644 --- a/src/checkpoints.h +++ b/src/checkpoints.h @@ -19,7 +19,7 @@ struct CCheckpointData; namespace Checkpoints { -//! 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/evo/simplifiedmns.cpp b/src/evo/simplifiedmns.cpp index 38c4844f0c..de447b683b 100644 --- a/src/evo/simplifiedmns.cpp +++ b/src/evo/simplifiedmns.cpp @@ -187,19 +187,18 @@ bool BuildSimplifiedMNListDiff(const uint256& baseBlockHash, const uint256& bloc const CBlockIndex* baseBlockIndex = chainActive.Genesis(); if (!baseBlockHash.IsNull()) { - auto it = mapBlockIndex.find(baseBlockHash); - if (it == mapBlockIndex.end()) { + baseBlockIndex = LookupBlockIndex(blockHash); + if (!baseBlockIndex) { errorRet = strprintf("block %s not found", baseBlockHash.ToString()); return false; } - baseBlockIndex = it->second; } - auto blockIt = mapBlockIndex.find(blockHash); - if (blockIt == mapBlockIndex.end()) { + + const CBlockIndex* blockIndex = LookupBlockIndex(blockHash); + if (!blockIndex) { errorRet = strprintf("block %s not found", blockHash.ToString()); return false; } - const CBlockIndex* blockIndex = blockIt->second; if (!chainActive.Contains(baseBlockIndex) || !chainActive.Contains(blockIndex)) { errorRet = strprintf("block %s and %s are not in the same chain", baseBlockHash.ToString(), blockHash.ToString()); diff --git a/src/governance/governance-object.cpp b/src/governance/governance-object.cpp index f48349f767..451ea31aa9 100644 --- a/src/governance/governance-object.cpp +++ b/src/governance/governance-object.cpp @@ -585,12 +585,9 @@ bool CGovernanceObject::IsCollateralValid(std::string& strError, bool& fMissingC AssertLockHeld(cs_main); int nConfirmationsIn = 0; if (nBlockHash != uint256()) { - BlockMap::iterator mi = mapBlockIndex.find(nBlockHash); - if (mi != mapBlockIndex.end() && (*mi).second) { - CBlockIndex* pindex = (*mi).second; - if (chainActive.Contains(pindex)) { - nConfirmationsIn += chainActive.Height() - pindex->nHeight + 1; - } + CBlockIndex* pindex = LookupBlockIndex(nBlockHash); + if (pindex && chainActive.Contains(pindex)) { + nConfirmationsIn += chainActive.Height() - pindex->nHeight + 1; } } diff --git a/src/init.cpp b/src/init.cpp index 2f5343cb0e..af42dbed31 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1925,6 +1925,8 @@ bool AppInitMain() uiInterface.InitMessage(_("Loading block index...")); + LOCK(cs_main); + do { const int64_t load_block_index_start_time = GetTimeMillis(); try { @@ -1971,8 +1973,9 @@ bool AppInitMain() // If the loaded chain has a wrong genesis, bail out immediately // (we're likely using a testnet datadir, or the other way around). - if (!mapBlockIndex.empty() && mapBlockIndex.count(chainparams.GetConsensus().hashGenesisBlock) == 0) + if (!mapBlockIndex.empty() && !LookupBlockIndex(chainparams.GetConsensus().hashGenesisBlock)) { return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?")); + } if (!chainparams.GetConsensus().hashDevnetGenesisBlock.IsNull() && !mapBlockIndex.empty() && mapBlockIndex.count(chainparams.GetConsensus().hashDevnetGenesisBlock) == 0) return InitError(_("Incorrect or no devnet genesis block found. Wrong datadir for devnet specified?")); @@ -2073,16 +2076,13 @@ bool AppInitMain() MIN_BLOCKS_TO_KEEP); } - { - LOCK(cs_main); - CBlockIndex* tip = chainActive.Tip(); - RPCNotifyBlockChange(true, tip); - if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) { - 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() + 2 * 60 * 60) { + 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(chainparams, pcoinsdbview.get(), gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL), diff --git a/src/llmq/quorums.cpp b/src/llmq/quorums.cpp index 52b9c5d923..4e66b00015 100644 --- a/src/llmq/quorums.cpp +++ b/src/llmq/quorums.cpp @@ -338,13 +338,12 @@ CQuorumCPtr CQuorumManager::GetQuorum(Consensus::LLMQType llmqType, const uint25 CBlockIndex* pindexQuorum; { LOCK(cs_main); - auto quorumIt = mapBlockIndex.find(quorumHash); - if (quorumIt == mapBlockIndex.end()) { + pindexQuorum = LookupBlockIndex(quorumHash); + if (!pindexQuorum) { LogPrint(BCLog::LLMQ, "CQuorumManager::%s -- block %s not found\n", __func__, quorumHash.ToString()); return nullptr; } - pindexQuorum = quorumIt->second; } return GetQuorum(llmqType, pindexQuorum); } diff --git a/src/llmq/quorums_blockprocessor.cpp b/src/llmq/quorums_blockprocessor.cpp index 04cafddac9..79f3818a2a 100644 --- a/src/llmq/quorums_blockprocessor.cpp +++ b/src/llmq/quorums_blockprocessor.cpp @@ -58,14 +58,14 @@ void CQuorumBlockProcessor::ProcessMessage(CNode* pfrom, const std::string& strC const CBlockIndex* pquorumIndex; { LOCK(cs_main); - if (!mapBlockIndex.count(qc.quorumHash)) { + pquorumIndex = LookupBlockIndex(qc.quorumHash); + if (!pquorumIndex) { LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- unknown block %s in commitment, peer=%d\n", __func__, qc.quorumHash.ToString(), pfrom->GetId()); // can't really punish the node here, as we might simply be the one that is on the wrong chain or not // fully synced return; } - pquorumIndex = mapBlockIndex[qc.quorumHash]; if (chainActive.Tip()->GetAncestor(pquorumIndex->nHeight) != pquorumIndex) { LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s -- block %s not in active chain, peer=%d\n", __func__, qc.quorumHash.ToString(), pfrom->GetId()); @@ -212,7 +212,7 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH return state.DoS(100, false, REJECT_INVALID, "bad-qc-height"); } - auto quorumIndex = mapBlockIndex.at(qc.quorumHash); + auto quorumIndex = LookupBlockIndex(qc.quorumHash); auto members = CLLMQUtils::GetAllQuorumMembers(params.type, quorumIndex); if (!qc.Verify(members, true)) { @@ -303,7 +303,7 @@ bool CQuorumBlockProcessor::UpgradeDB() if (qc.IsNull()) { continue; } - auto quorumIndex = mapBlockIndex.at(qc.quorumHash); + auto quorumIndex = LookupBlockIndex(qc.quorumHash); evoDb.GetRawDB().Write(std::make_pair(DB_MINED_COMMITMENT, std::make_pair(qc.llmqType, qc.quorumHash)), std::make_pair(qc, pindex->GetBlockHash())); evoDb.GetRawDB().Write(BuildInversedHeightKey((Consensus::LLMQType)qc.llmqType, pindex->nHeight), quorumIndex->nHeight); } diff --git a/src/llmq/quorums_chainlocks.cpp b/src/llmq/quorums_chainlocks.cpp index 3000670041..2e497d64e3 100644 --- a/src/llmq/quorums_chainlocks.cpp +++ b/src/llmq/quorums_chainlocks.cpp @@ -151,21 +151,20 @@ void CChainLocksHandler::ProcessNewChainLock(NodeId from, const llmq::CChainLock CInv inv(MSG_CLSIG, hash); g_connman->RelayInv(inv, LLMQS_PROTO_VERSION); - auto blockIt = mapBlockIndex.find(clsig.blockHash); - if (blockIt == mapBlockIndex.end()) { + const CBlockIndex* pindex = LookupBlockIndex(clsig.blockHash); + if (!pindex) { // we don't know the block/header for this CLSIG yet, so bail out for now // when the block or the header later comes in, we will enforce the correct chain return; } - if (blockIt->second->nHeight != clsig.nHeight) { + if (pindex->nHeight != clsig.nHeight) { // Should not happen, same as the conflict check from above. LogPrintf("CChainLocksHandler::%s -- height of CLSIG (%s) does not match the specified block's height (%d)\n", - __func__, clsig.ToString(), blockIt->second->nHeight); + __func__, clsig.ToString(), pindex->nHeight); return; } - const CBlockIndex* pindex = blockIt->second; bestChainLockWithKnownBlock = bestChainLock; bestChainLockBlockIndex = pindex; } @@ -431,7 +430,7 @@ CChainLocksHandler::BlockTxs::mapped_type CChainLocksHandler::GetBlockTxs(const uint32_t blockTime; { LOCK(cs_main); - auto pindex = mapBlockIndex.at(blockHash); + auto pindex = LookupBlockIndex(blockHash); CBlock block; if (!ReadBlockFromDisk(block, pindex, Params().GetConsensus())) { return nullptr; @@ -536,7 +535,7 @@ void CChainLocksHandler::EnforceBestChainLock() // the trigger later appears, this should bring us to the correct chain eventually. Please note that this does // NOT enforce invalid blocks in any way, it just causes re-validation. if (!currentBestChainLockBlockIndex->IsValid()) { - ResetBlockFailureFlags(mapBlockIndex.at(currentBestChainLockBlockIndex->GetBlockHash())); + ResetBlockFailureFlags(LookupBlockIndex(currentBestChainLockBlockIndex->GetBlockHash())); } activateNeeded = chainActive.Tip()->GetAncestor(currentBestChainLockBlockIndex->nHeight) != currentBestChainLockBlockIndex; @@ -596,7 +595,7 @@ void CChainLocksHandler::DoInvalidateBlock(const CBlockIndex* pindex) auto& params = Params(); // get the non-const pointer - CBlockIndex* pindex2 = mapBlockIndex[pindex->GetBlockHash()]; + CBlockIndex* pindex2 = LookupBlockIndex(pindex->GetBlockHash()); CValidationState state; if (!InvalidateBlock(state, params, pindex2)) { @@ -693,7 +692,7 @@ void CChainLocksHandler::Cleanup() } for (auto it = blockTxs.begin(); it != blockTxs.end(); ) { - auto pindex = mapBlockIndex.at(it->first); + auto pindex = LookupBlockIndex(it->first); if (InternalHasChainLock(pindex->nHeight, pindex->GetBlockHash())) { for (auto& txid : *it->second) { txFirstSeenTime.erase(txid); @@ -712,7 +711,7 @@ void CChainLocksHandler::Cleanup() // tx has vanished, probably due to conflicts it = txFirstSeenTime.erase(it); } else if (!hashBlock.IsNull()) { - auto pindex = mapBlockIndex.at(hashBlock); + auto pindex = LookupBlockIndex(hashBlock); if (chainActive.Tip()->GetAncestor(pindex->nHeight) == pindex && chainActive.Height() - pindex->nHeight >= 6) { // tx got confirmed >= 6 times, so we can stop keeping track of it it = txFirstSeenTime.erase(it); diff --git a/src/llmq/quorums_commitment.cpp b/src/llmq/quorums_commitment.cpp index cea4ba4a34..007ab063f5 100644 --- a/src/llmq/quorums_commitment.cpp +++ b/src/llmq/quorums_commitment.cpp @@ -145,11 +145,11 @@ bool CheckLLMQCommitment(const CTransaction& tx, const CBlockIndex* pindexPrev, return state.DoS(100, false, REJECT_INVALID, "bad-qc-height"); } - if (!mapBlockIndex.count(qcTx.commitment.quorumHash)) { + const CBlockIndex* pindexQuorum = LookupBlockIndex(qcTx.commitment.quorumHash); + if (!pindexQuorum) { return state.DoS(100, false, REJECT_INVALID, "bad-qc-quorum-hash"); } - const CBlockIndex* pindexQuorum = mapBlockIndex[qcTx.commitment.quorumHash]; if (pindexQuorum != pindexPrev->GetAncestor(pindexQuorum->nHeight)) { // not part of active chain diff --git a/src/llmq/quorums_debug.cpp b/src/llmq/quorums_debug.cpp index 44b8e25d95..7178277861 100644 --- a/src/llmq/quorums_debug.cpp +++ b/src/llmq/quorums_debug.cpp @@ -27,10 +27,7 @@ UniValue CDKGDebugSessionStatus::ToJson(int detailLevel) const const CBlockIndex* pindex = nullptr; { LOCK(cs_main); - auto it = mapBlockIndex.find(quorumHash); - if (it != mapBlockIndex.end()) { - pindex = it->second; - } + pindex = LookupBlockIndex(quorumHash); } if (pindex != nullptr) { dmnMembers = CLLMQUtils::GetAllQuorumMembers((Consensus::LLMQType) llmqType, pindex); diff --git a/src/llmq/quorums_dkgsessionhandler.cpp b/src/llmq/quorums_dkgsessionhandler.cpp index ea3ba80809..7f6a0d9277 100644 --- a/src/llmq/quorums_dkgsessionhandler.cpp +++ b/src/llmq/quorums_dkgsessionhandler.cpp @@ -518,7 +518,7 @@ void CDKGSessionHandler::HandleDKGRound() const CBlockIndex* pindexQuorum; { LOCK(cs_main); - pindexQuorum = mapBlockIndex.at(curQuorumHash); + pindexQuorum = LookupBlockIndex(curQuorumHash); } if (!InitNewQuorum(pindexQuorum)) { diff --git a/src/llmq/quorums_instantsend.cpp b/src/llmq/quorums_instantsend.cpp index eec77396de..821cd7f31e 100644 --- a/src/llmq/quorums_instantsend.cpp +++ b/src/llmq/quorums_instantsend.cpp @@ -527,7 +527,7 @@ bool CInstantSendManager::CheckCanLock(const COutPoint& outpoint, bool printDebu int nTxAge; { LOCK(cs_main); - pindexMined = mapBlockIndex.at(hashBlock); + pindexMined = LookupBlockIndex(hashBlock); nTxAge = chainActive.Height() - pindexMined->nHeight + 1; } @@ -895,7 +895,7 @@ void CInstantSendManager::ProcessInstantSendLock(NodeId from, const uint256& has if (!hashBlock.IsNull()) { { LOCK(cs_main); - pindexMined = mapBlockIndex.at(hashBlock); + pindexMined = LookupBlockIndex(hashBlock); } // Let's see if the TX that was locked by this islock is already mined in a ChainLocked block. If yes, @@ -1308,7 +1308,7 @@ void CInstantSendManager::ResolveBlockConflicts(const uint256& islockHash, const LOCK(cs_main); CValidationState state; // need non-const pointer - auto pindex2 = mapBlockIndex.at(pindex->GetBlockHash()); + auto pindex2 = LookupBlockIndex(pindex->GetBlockHash()); if (!InvalidateBlock(state, Params(), pindex2)) { LogPrintf("CInstantSendManager::%s -- InvalidateBlock failed: %s\n", __func__, FormatStateMessage(state)); // This should not have happened and we are in a state were it's not safe to continue anymore diff --git a/src/net_processing.cpp b/src/net_processing.cpp index e2c0ac75b1..3994c9f15e 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -518,10 +518,11 @@ void ProcessBlockAvailability(NodeId nodeid) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { assert(state != nullptr); if (!state->hashLastUnknownBlock.IsNull()) { - BlockMap::iterator itOld = mapBlockIndex.find(state->hashLastUnknownBlock); - if (itOld != mapBlockIndex.end() && itOld->second->nChainWork > 0) { - if (state->pindexBestKnownBlock == nullptr || itOld->second->nChainWork >= state->pindexBestKnownBlock->nChainWork) - state->pindexBestKnownBlock = itOld->second; + const CBlockIndex* pindex = LookupBlockIndex(state->hashLastUnknownBlock); + if (pindex && pindex->nChainWork > 0) { + if (state->pindexBestKnownBlock == nullptr || pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) { + state->pindexBestKnownBlock = pindex; + } state->hashLastUnknownBlock.SetNull(); } } @@ -534,11 +535,12 @@ void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) EXCLUSIVE_LOCKS 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; + if (state->pindexBestKnownBlock == nullptr || pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) { + state->pindexBestKnownBlock = pindex; + } } else { // An unknown block was announced; just assume that the latest one is the best one. state->hashLastUnknownBlock = hash; @@ -1351,7 +1353,7 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main) } case MSG_BLOCK: - return mapBlockIndex.count(inv.hash); + return LookupBlockIndex(inv.hash) != nullptr; /* Dash Related Inventory Messages @@ -1443,11 +1445,10 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c 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(BLOCK_VALID_SCRIPTS) && - mi->second->IsValid(BLOCK_VALID_TREE)) { + const CBlockIndex* pindex = LookupBlockIndex(inv.hash); + if (pindex) { + if (pindex->nChainTx && !pindex->IsValid(BLOCK_VALID_SCRIPTS) && + pindex->IsValid(BLOCK_VALID_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 AcceptBlock). @@ -1465,9 +1466,9 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c } 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 block that isn't in the main chain\n", __func__, pfrom->GetId()); } @@ -1475,7 +1476,7 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c const CNetMsgMaker msgMaker(pfrom->GetSendVersion()); // disconnect node in case we have reached the outbound limit for serving historical blocks // never disconnect whitelisted nodes - if (send && connman->OutboundTargetReached(true) && ( ((pindexBestHeader != nullptr) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.type == MSG_FILTERED_BLOCK) && !pfrom->fWhitelisted) + if (send && connman->OutboundTargetReached(true) && ( ((pindexBestHeader != nullptr) && (pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.type == MSG_FILTERED_BLOCK) && !pfrom->fWhitelisted) { LogPrint(BCLog::NET, "historical block serving limit reached, disconnect peer=%d\n", pfrom->GetId()); @@ -1485,7 +1486,7 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c } // Avoid leaking prune-height by never sending blocks below the NODE_NETWORK_LIMITED threshold if (send && !pfrom->fWhitelisted && ( - (((pfrom->GetLocalServices() & NODE_NETWORK_LIMITED) == NODE_NETWORK_LIMITED) && ((pfrom->GetLocalServices() & NODE_NETWORK) != NODE_NETWORK) && (chainActive.Tip()->nHeight - mi->second->nHeight > (int)NODE_NETWORK_LIMITED_MIN_BLOCKS + 2 /* add two blocks buffer extension for possible races */) ) + (((pfrom->GetLocalServices() & NODE_NETWORK_LIMITED) == NODE_NETWORK_LIMITED) && ((pfrom->GetLocalServices() & NODE_NETWORK) != NODE_NETWORK) && (chainActive.Tip()->nHeight - pindex->nHeight > (int)NODE_NETWORK_LIMITED_MIN_BLOCKS + 2 /* add two blocks buffer extension for possible races */) ) )) { LogPrint(BCLog::NET, "Ignore block request below NODE_NETWORK_LIMITED threshold from peer=%d\n", pfrom->GetId()); @@ -1495,15 +1496,15 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c } // Pruned nodes may have deleted the block, so check whether // it's available before trying to send. - if (send && (mi->second->nStatus & BLOCK_HAVE_DATA)) + if (send && (pindex->nStatus & BLOCK_HAVE_DATA)) { std::shared_ptr pblock; - if (a_recent_block && a_recent_block->GetHash() == (*mi).second->GetBlockHash()) { + if (a_recent_block && 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, consensusParams)) + if (!ReadBlockFromDisk(*pblockRead, pindex, consensusParams)) assert(!"cannot load block from disk"); pblock = pblockRead; } @@ -1540,9 +1541,9 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c // and we don't feel like constructing the object for them, so // instead we respond with the full, non-compact block. if (CanDirectFetch(consensusParams) && - mi->second->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) { + pindex->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) { if (a_recent_compact_block && - a_recent_compact_block->header.GetHash() == mi->second->GetBlockHash()) { + a_recent_compact_block->header.GetHash() == pindex->GetBlockHash()) { connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::CMPCTBLOCK, *a_recent_compact_block)); } else { CBlockHeaderAndShortTxIDs cmpctblock(*pblock); @@ -1798,7 +1799,7 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve // 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() && nCount < MAX_BLOCKS_TO_ANNOUNCE) { + if (!LookupBlockIndex(headers[0].hashPrevBlock) && nCount < MAX_BLOCKS_TO_ANNOUNCE) { nodestate->nUnconnectingHeaders++; connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256())); LogPrint(BCLog::NET, "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n", @@ -1828,7 +1829,7 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve // 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; } } @@ -1844,7 +1845,7 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve } else { LogPrint(BCLog::NET, "peer=%d: invalid header received\n", pfrom->GetId()); } - if (punish_duplicate_invalid && mapBlockIndex.find(first_invalid_header.GetHash()) != mapBlockIndex.end()) { + if (punish_duplicate_invalid && LookupBlockIndex(first_invalid_header.GetHash())) { // Goal: don't allow outbound peers to use up our outbound // connection slots if they are on incompatible chains. // @@ -2688,13 +2689,13 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr LOCK(cs_main); - BlockMap::iterator it = mapBlockIndex.find(req.blockhash); - if (it == mapBlockIndex.end() || !(it->second->nStatus & BLOCK_HAVE_DATA)) { + const CBlockIndex* pindex = LookupBlockIndex(req.blockhash); + if (!pindex || !(pindex->nStatus & BLOCK_HAVE_DATA)) { LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block we don't have\n", 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 @@ -2712,7 +2713,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr } CBlock block; - bool ret = ReadBlockFromDisk(block, it->second, chainparams.GetConsensus()); + bool ret = ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()); assert(ret); SendBlockTransactions(block, req, pfrom, connman); @@ -2741,10 +2742,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr 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, "%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom->GetId()); @@ -2993,14 +2994,14 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr { 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()) connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256())); return true; } - if (mapBlockIndex.find(cmpctblock.header.GetHash()) == mapBlockIndex.end()) { + if (!LookupBlockIndex(cmpctblock.header.GetHash())) { received_new_header = true; } } @@ -4047,9 +4048,8 @@ bool PeerLogicValidation::SendMessages(CNode* pto) // then send all headers past that one. If we come across any // 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; @@ -4142,9 +4142,8 @@ bool PeerLogicValidation::SendMessages(CNode* pto) // in the past. 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/node/coinstats.cpp b/src/node/coinstats.cpp index 097b7cd2e6..3ae0f084dc 100644 --- a/src/node/coinstats.cpp +++ b/src/node/coinstats.cpp @@ -49,8 +49,7 @@ bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats) stats.hashBlock = pcursor->GetBestBlock(); { LOCK(cs_main); - // stats.nHeight = LookupBlockIndex(stats.hashBlock)->nHeight; - stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight; + stats.nHeight = LookupBlockIndex(stats.hashBlock)->nHeight; } ss << stats.hashBlock; uint256 prevkey; diff --git a/src/rest.cpp b/src/rest.cpp index 0c94fdcb9e..ba978a97ec 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -147,8 +147,7 @@ static bool rest_headers(HTTPRequest* req, 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() == (unsigned long)count) @@ -212,10 +211,11 @@ static bool rest_block(HTTPRequest* req, 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 (IsBlockPruned(pblockindex)) return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not available (pruned data)"); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index e11a368e0f..0e2462167f 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -795,10 +795,10 @@ UniValue getblockheader(const JSONRPCRequest& request) if (!request.params[1].isNull()) 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) { @@ -1064,10 +1064,11 @@ UniValue getblock(const JSONRPCRequest& request) verbosity = request.params[1].get_bool() ? 1 : 0; } - 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]; const CBlock block = GetBlockChecked(pblockindex); if (verbosity <= 0) @@ -1235,8 +1236,7 @@ UniValue gettxout(const JSONRPCRequest& request) } } - 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.nHeight == MEMPOOL_HEIGHT) { ret.pushKV("confirmations", 0); @@ -1661,10 +1661,10 @@ UniValue preciousblock(const JSONRPCRequest& request) { 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; @@ -1697,10 +1697,11 @@ UniValue invalidateblock(const JSONRPCRequest& request) { 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(state, Params(), pblockindex); } @@ -1735,10 +1736,11 @@ UniValue reconsiderblock(const JSONRPCRequest& request) { 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 +1787,10 @@ UniValue getchaintxstats(const JSONRPCRequest& request) } 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 index 6a22055445..9d9ec58564 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -419,9 +419,8 @@ UniValue getblocktemplate(const JSONRPCRequest& request) throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "Block decode failed"); 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(BLOCK_VALID_SCRIPTS)) return "duplicate"; if (pindex->nStatus & BLOCK_FAILED_MASK) @@ -761,9 +760,8 @@ UniValue submitblock(const JSONRPCRequest& request) 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(BLOCK_VALID_SCRIPTS)) { return "duplicate"; } diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 6e0751bb81..e304271d49 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -78,9 +78,8 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, UniValue& entry) bool chainLock = false; 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("height", pindex->nHeight); entry.pushKV("confirmations", 1 + chainActive.Height() - pindex->nHeight); @@ -202,11 +201,10 @@ UniValue getrawtransaction(const JSONRPCRequest& request) 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); } @@ -285,9 +283,10 @@ UniValue gettxoutproof(const JSONRPCRequest& request) 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. for (const auto& tx : setTxids) { @@ -304,9 +303,10 @@ UniValue gettxoutproof(const JSONRPCRequest& request) CTransactionRef tx; if (!GetTransaction(oneTxid, tx, Params().GetConsensus(), hashBlock, false) || hashBlock.IsNull()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "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; @@ -357,8 +357,10 @@ UniValue verifytxoutproof(const JSONRPCRequest& request) 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"); + } for (const uint256& hash : vMatch) res.push_back(hash.GetHex()); diff --git a/src/validation.cpp b/src/validation.cpp index 1743170723..acb8eda5a1 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -292,13 +292,13 @@ namespace { CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator) { + AssertLockHeld(cs_main); + // Find the latest block common to locator and chain - we expect that // locator.vHave is sorted descending by height. 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; } @@ -1427,7 +1427,7 @@ bool CScriptCheck::operator()() { int GetSpendHeight(const CCoinsViewCache& inputs) { LOCK(cs_main); - CBlockIndex* pindexPrev = mapBlockIndex.find(inputs.GetBestBlock())->second; + CBlockIndex* pindexPrev = LookupBlockIndex(inputs.GetBestBlock()); return pindexPrev->nHeight + 1; } @@ -3324,6 +3324,8 @@ bool ResetBlockFailureFlags(CBlockIndex *pindex) { CBlockIndex* CChainState::AddToBlockIndex(const CBlockHeader& block, enum BlockStatus nStatus) { + AssertLockHeld(cs_main); + // Check for duplicate uint256 hash = block.GetHash(); BlockMap::iterator it = mapBlockIndex.find(hash); @@ -3717,7 +3719,6 @@ bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState& // TODO : ENABLE BLOCK CACHE IN SPECIFIC CASES if (hash != chainparams.GetConsensus().hashGenesisBlock) { - if (miSelf != mapBlockIndex.end()) { // Block header is already known. pindex = miSelf->second; @@ -4198,6 +4199,8 @@ fs::path GetBlockPosFilename(const CDiskBlockPos &pos, const char *prefix) CBlockIndex * CChainState::InsertBlockIndex(const uint256& hash) { + AssertLockHeld(cs_main); + if (hash.IsNull()) return nullptr; @@ -4342,6 +4345,8 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_RE bool LoadChainTip(const CChainParams& chainparams) { + AssertLockHeld(cs_main); + if (chainActive.Tip() && chainActive.Tip()->GetBlockHash() == pcoinsTip->GetBestBlock()) return true; if (pcoinsTip->GetBestBlock().IsNull() && mapBlockIndex.size() == 1) { @@ -4356,10 +4361,11 @@ bool LoadChainTip(const CChainParams& chainparams) } // 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(); @@ -4749,26 +4755,31 @@ bool LoadExternalBlockFile(const CChainParams& chainparams, FILE* fileIn, CDiskB 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 & BLOCK_HAVE_DATA) == 0) { + { LOCK(cs_main); - CValidationState state; - if (g_chainstate.AcceptBlock(pblock, state, chainparams, nullptr, true, dbp, nullptr)) - nLoaded++; - if (state.IsError()) - break; - } 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); + // 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; + } + + // process in case the block isn't known yet + CBlockIndex* pindex = LookupBlockIndex(hash); + if (!pindex || (pindex->nStatus & BLOCK_HAVE_DATA) == 0) { + CValidationState state; + if (g_chainstate.AcceptBlock(pblock, state, chainparams, nullptr, 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); + } } // Activate the genesis block so normal node progress can continue diff --git a/src/validation.h b/src/validation.h index 3ec3bf77ad..a9373e6e7b 100644 --- a/src/validation.h +++ b/src/validation.h @@ -441,6 +441,13 @@ public: /** Replay blocks that aren't fully applied to the database. */ bool ReplayBlocks(const CChainParams& params, CCoinsView* view); +inline CBlockIndex* LookupBlockIndex(const uint256& hash) +{ + AssertLockHeld(cs_main); + BlockMap::const_iterator it = mapBlockIndex.find(hash); + return it == mapBlockIndex.end() ? nullptr : it->second; +} + /** Find the last common block between the parameter chain and a locator. */ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator); diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index b0ef5796fd..3e6ceb6806 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -343,9 +343,10 @@ UniValue importprunedfunds(const JSONRPCRequest& request) if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) == 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"); + } std::vector::const_iterator it; if ((it = std::find(vMatch.begin(), vMatch.end(), hashTx))==vMatch.end()) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index b3dc4a5ef5..fba2e7260d 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -106,7 +106,7 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry) { 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()); } @@ -1943,11 +1943,10 @@ UniValue listsinceblock(const JSONRPCRequest& request) 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 index 6183d337b1..a27eb709ae 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1369,11 +1369,9 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx) LOCK2(cs_main, cs_wallet); // check "LOCK2(cs_main, pwallet->cs_wallet);" in WalletBatch::LoadWallet() 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 block is still unknown or not yet part of the main chain, @@ -4918,10 +4916,10 @@ void CWallet::GetKeyBirthTimes(std::map &mapKeyBirth) c 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)) { + CBlockIndex* pindex = LookupBlockIndex(wtx.hashBlock); + if (pindex && chainActive.Contains(pindex)) { // ... which are already in a block - int nHeight = blit->second->nHeight; + int nHeight = pindex->nHeight; for (const CTxOut &txout : wtx.tx->vout) { // iterate over all their outputs CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey); @@ -4929,7 +4927,7 @@ void CWallet::GetKeyBirthTimes(std::map &mapKeyBirth) c // ... and all their affected keys std::map::iterator rit = mapKeyFirstBlock.find(keyid); if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight) - rit->second = blit->second; + rit->second = pindex; } vAffected.clear(); } @@ -4966,7 +4964,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; @@ -4997,7 +5000,7 @@ unsigned int CWallet::ComputeTimeSmart(const CWalletTx& wtx) const } } - 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__, wtx.GetHash().ToString(), wtx.hashBlock.ToString()); @@ -5245,6 +5248,8 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& // 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)) { @@ -5569,29 +5574,17 @@ int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const int nResult; if (hashUnset()) - nResult = 0; - else { - AssertLockHeld(cs_main); + return 0; - // Find the block it claims to be in - BlockMap::iterator mi = mapBlockIndex.find(hashBlock); - if (mi == mapBlockIndex.end()) - nResult = 0; - else { - CBlockIndex* pindex = (*mi).second; - if (!pindex || !chainActive.Contains(pindex)) - nResult = 0; - else { - pindexRet = pindex; - nResult = ((nIndex == -1) ? (-1) : 1) * (chainActive.Height() - pindex->nHeight + 1); + AssertLockHeld(cs_main); - if (nResult == 0 && !mempool.exists(GetHash())) - return -1; // Not in chain, not in mempool - } - } - } + // Find the block it claims to be in + CBlockIndex* pindex = LookupBlockIndex(hashBlock); + if (!pindex || !chainActive.Contains(pindex)) + return 0; - return nResult; + pindexRet = pindex; + return ((nIndex == -1) ? (-1) : 1) * (chainActive.Height() - pindex->nHeight + 1); } bool CMerkleTx::IsLockedByInstantSend() const