Skip to content

Commit d42a4fe

Browse files
committed
Merge #11041: Add LookupBlockIndex
92fabcd Add LookupBlockIndex function (João Barbosa) 43a32b7 Add missing cs_lock in CreateWalletFromFile (João Barbosa) f814a3e Fix cs_main lock in LoadExternalBlockFile (João Barbosa) c651df8 Lock cs_main while loading block index in AppInitMain (João Barbosa) 02de6a6 Assert cs_main is held when accessing mapBlockIndex (João Barbosa) Pull request description: Replace all `mapBlockIndex` lookups with the new `LookupBlockIndex()`. In some cases it avoids a second lookup. Tree-SHA512: ca31118f028a19721f2191d86f2dd398144d04df345694575a64aeb293be2f85785201480c3c578a0ec99690516205708558c0fd4168b09313378fd4e60a8412
2 parents af88094 + 92fabcd commit d42a4fe

14 files changed

+169
-152
lines changed

src/checkpoints.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@ namespace Checkpoints {
2121
for (const MapCheckpoints::value_type& i : reverse_iterate(checkpoints))
2222
{
2323
const uint256& hash = i.second;
24-
BlockMap::const_iterator t = mapBlockIndex.find(hash);
25-
if (t != mapBlockIndex.end())
26-
return t->second;
24+
CBlockIndex* pindex = LookupBlockIndex(hash);
25+
if (pindex) {
26+
return pindex;
27+
}
2728
}
2829
return nullptr;
2930
}

src/checkpoints.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ struct CCheckpointData;
1919
namespace Checkpoints
2020
{
2121

22-
//! Returns last CBlockIndex* in mapBlockIndex that is a checkpoint
22+
//! Returns last CBlockIndex* that is a checkpoint
2323
CBlockIndex* GetLastCheckpoint(const CCheckpointData& data);
2424

2525
} //namespace Checkpoints

src/init.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,8 @@ bool AppInitMain()
14241424

14251425
uiInterface.InitMessage(_("Loading block index..."));
14261426

1427+
LOCK(cs_main);
1428+
14271429
nStart = GetTimeMillis();
14281430
do {
14291431
try {
@@ -1457,8 +1459,9 @@ bool AppInitMain()
14571459

14581460
// If the loaded chain has a wrong genesis, bail out immediately
14591461
// (we're likely using a testnet datadir, or the other way around).
1460-
if (!mapBlockIndex.empty() && mapBlockIndex.count(chainparams.GetConsensus().hashGenesisBlock) == 0)
1462+
if (!mapBlockIndex.empty() && !LookupBlockIndex(chainparams.GetConsensus().hashGenesisBlock)) {
14611463
return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
1464+
}
14621465

14631466
// Check for changed -txindex state
14641467
if (fTxIndex != gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
@@ -1532,16 +1535,13 @@ bool AppInitMain()
15321535
MIN_BLOCKS_TO_KEEP);
15331536
}
15341537

1535-
{
1536-
LOCK(cs_main);
1537-
CBlockIndex* tip = chainActive.Tip();
1538-
RPCNotifyBlockChange(true, tip);
1539-
if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) {
1540-
strLoadError = _("The block database contains a block which appears to be from the future. "
1541-
"This may be due to your computer's date and time being set incorrectly. "
1542-
"Only rebuild the block database if you are sure that your computer's date and time are correct");
1543-
break;
1544-
}
1538+
CBlockIndex* tip = chainActive.Tip();
1539+
RPCNotifyBlockChange(true, tip);
1540+
if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) {
1541+
strLoadError = _("The block database contains a block which appears to be from the future. "
1542+
"This may be due to your computer's date and time being set incorrectly. "
1543+
"Only rebuild the block database if you are sure that your computer's date and time are correct");
1544+
break;
15451545
}
15461546

15471547
if (!CVerifyDB().VerifyDB(chainparams, pcoinsdbview.get(), gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL),

src/net_processing.cpp

Lines changed: 41 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -374,10 +374,11 @@ void ProcessBlockAvailability(NodeId nodeid) {
374374
assert(state != nullptr);
375375

376376
if (!state->hashLastUnknownBlock.IsNull()) {
377-
BlockMap::iterator itOld = mapBlockIndex.find(state->hashLastUnknownBlock);
378-
if (itOld != mapBlockIndex.end() && itOld->second->nChainWork > 0) {
379-
if (state->pindexBestKnownBlock == nullptr || itOld->second->nChainWork >= state->pindexBestKnownBlock->nChainWork)
380-
state->pindexBestKnownBlock = itOld->second;
377+
const CBlockIndex* pindex = LookupBlockIndex(state->hashLastUnknownBlock);
378+
if (pindex && pindex->nChainWork > 0) {
379+
if (state->pindexBestKnownBlock == nullptr || pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) {
380+
state->pindexBestKnownBlock = pindex;
381+
}
381382
state->hashLastUnknownBlock.SetNull();
382383
}
383384
}
@@ -390,11 +391,12 @@ void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) {
390391

391392
ProcessBlockAvailability(nodeid);
392393

393-
BlockMap::iterator it = mapBlockIndex.find(hash);
394-
if (it != mapBlockIndex.end() && it->second->nChainWork > 0) {
394+
const CBlockIndex* pindex = LookupBlockIndex(hash);
395+
if (pindex && pindex->nChainWork > 0) {
395396
// An actually better block was announced.
396-
if (state->pindexBestKnownBlock == nullptr || it->second->nChainWork >= state->pindexBestKnownBlock->nChainWork)
397-
state->pindexBestKnownBlock = it->second;
397+
if (state->pindexBestKnownBlock == nullptr || pindex->nChainWork >= state->pindexBestKnownBlock->nChainWork) {
398+
state->pindexBestKnownBlock = pindex;
399+
}
398400
} else {
399401
// An unknown block was announced; just assume that the latest one is the best one.
400402
state->hashLastUnknownBlock = hash;
@@ -1015,7 +1017,7 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
10151017
}
10161018
case MSG_BLOCK:
10171019
case MSG_WITNESS_BLOCK:
1018-
return mapBlockIndex.count(inv.hash);
1020+
return LookupBlockIndex(inv.hash) != nullptr;
10191021
}
10201022
// Don't know what it is, just say we already got one
10211023
return true;
@@ -1082,11 +1084,10 @@ void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
10821084
bool need_activate_chain = false;
10831085
{
10841086
LOCK(cs_main);
1085-
BlockMap::iterator mi = mapBlockIndex.find(inv.hash);
1086-
if (mi != mapBlockIndex.end())
1087-
{
1088-
if (mi->second->nChainTx && !mi->second->IsValid(BLOCK_VALID_SCRIPTS) &&
1089-
mi->second->IsValid(BLOCK_VALID_TREE)) {
1087+
const CBlockIndex* pindex = LookupBlockIndex(inv.hash);
1088+
if (pindex) {
1089+
if (pindex->nChainTx && !pindex->IsValid(BLOCK_VALID_SCRIPTS) &&
1090+
pindex->IsValid(BLOCK_VALID_TREE)) {
10901091
// If we have the block and all of its parents, but have not yet validated it,
10911092
// we might be in the middle of connecting it (ie in the unlock of cs_main
10921093
// before ActivateBestChain but after AcceptBlock).
@@ -1102,17 +1103,17 @@ void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
11021103
}
11031104

11041105
LOCK(cs_main);
1105-
BlockMap::iterator mi = mapBlockIndex.find(inv.hash);
1106-
if (mi != mapBlockIndex.end()) {
1107-
send = BlockRequestAllowed(mi->second, consensusParams);
1106+
const CBlockIndex* pindex = LookupBlockIndex(inv.hash);
1107+
if (pindex) {
1108+
send = BlockRequestAllowed(pindex, consensusParams);
11081109
if (!send) {
11091110
LogPrint(BCLog::NET, "%s: ignoring request from peer=%i for old block that isn't in the main chain\n", __func__, pfrom->GetId());
11101111
}
11111112
}
11121113
const CNetMsgMaker msgMaker(pfrom->GetSendVersion());
11131114
// disconnect node in case we have reached the outbound limit for serving historical blocks
11141115
// never disconnect whitelisted nodes
1115-
if (send && connman->OutboundTargetReached(true) && ( ((pindexBestHeader != nullptr) && (pindexBestHeader->GetBlockTime() - mi->second->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.type == MSG_FILTERED_BLOCK) && !pfrom->fWhitelisted)
1116+
if (send && connman->OutboundTargetReached(true) && ( ((pindexBestHeader != nullptr) && (pindexBestHeader->GetBlockTime() - pindex->GetBlockTime() > HISTORICAL_BLOCK_AGE)) || inv.type == MSG_FILTERED_BLOCK) && !pfrom->fWhitelisted)
11161117
{
11171118
LogPrint(BCLog::NET, "historical block serving limit reached, disconnect peer=%d\n", pfrom->GetId());
11181119

@@ -1122,7 +1123,7 @@ void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
11221123
}
11231124
// Avoid leaking prune-height by never sending blocks below the NODE_NETWORK_LIMITED threshold
11241125
if (send && !pfrom->fWhitelisted && (
1125-
(((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 */) )
1126+
(((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 */) )
11261127
)) {
11271128
LogPrint(BCLog::NET, "Ignore block request below NODE_NETWORK_LIMITED threshold from peer=%d\n", pfrom->GetId());
11281129

@@ -1132,15 +1133,15 @@ void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
11321133
}
11331134
// Pruned nodes may have deleted the block, so check whether
11341135
// it's available before trying to send.
1135-
if (send && (mi->second->nStatus & BLOCK_HAVE_DATA))
1136+
if (send && (pindex->nStatus & BLOCK_HAVE_DATA))
11361137
{
11371138
std::shared_ptr<const CBlock> pblock;
1138-
if (a_recent_block && a_recent_block->GetHash() == (*mi).second->GetBlockHash()) {
1139+
if (a_recent_block && a_recent_block->GetHash() == pindex->GetBlockHash()) {
11391140
pblock = a_recent_block;
11401141
} else {
11411142
// Send block from disk
11421143
std::shared_ptr<CBlock> pblockRead = std::make_shared<CBlock>();
1143-
if (!ReadBlockFromDisk(*pblockRead, (*mi).second, consensusParams))
1144+
if (!ReadBlockFromDisk(*pblockRead, pindex, consensusParams))
11441145
assert(!"cannot load block from disk");
11451146
pblock = pblockRead;
11461147
}
@@ -1182,8 +1183,8 @@ void static ProcessGetBlockData(CNode* pfrom, const Consensus::Params& consensus
11821183
// instead we respond with the full, non-compact block.
11831184
bool fPeerWantsWitness = State(pfrom->GetId())->fWantsCmpctWitness;
11841185
int nSendFlags = fPeerWantsWitness ? 0 : SERIALIZE_TRANSACTION_NO_WITNESS;
1185-
if (CanDirectFetch(consensusParams) && mi->second->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) {
1186-
if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == mi->second->GetBlockHash()) {
1186+
if (CanDirectFetch(consensusParams) && pindex->nHeight >= chainActive.Height() - MAX_CMPCTBLOCK_DEPTH) {
1187+
if ((fPeerWantsWitness || !fWitnessesPresentInARecentCompactBlock) && a_recent_compact_block && a_recent_compact_block->header.GetHash() == pindex->GetBlockHash()) {
11871188
connman->PushMessage(pfrom, msgMaker.Make(nSendFlags, NetMsgType::CMPCTBLOCK, *a_recent_compact_block));
11881189
} else {
11891190
CBlockHeaderAndShortTxIDs cmpctblock(*pblock, fPeerWantsWitness);
@@ -1323,7 +1324,7 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve
13231324
// don't connect before giving DoS points
13241325
// - Once a headers message is received that is valid and does connect,
13251326
// nUnconnectingHeaders gets reset back to 0.
1326-
if (mapBlockIndex.find(headers[0].hashPrevBlock) == mapBlockIndex.end() && nCount < MAX_BLOCKS_TO_ANNOUNCE) {
1327+
if (!LookupBlockIndex(headers[0].hashPrevBlock) && nCount < MAX_BLOCKS_TO_ANNOUNCE) {
13271328
nodestate->nUnconnectingHeaders++;
13281329
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256()));
13291330
LogPrint(BCLog::NET, "received header %s: missing prev block %s, sending getheaders (%d) to end (peer=%d, nUnconnectingHeaders=%d)\n",
@@ -1353,7 +1354,7 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve
13531354

13541355
// If we don't have the last header, then they'll have given us
13551356
// something new (if these headers are valid).
1356-
if (mapBlockIndex.find(hashLastBlock) == mapBlockIndex.end()) {
1357+
if (!LookupBlockIndex(hashLastBlock)) {
13571358
received_new_header = true;
13581359
}
13591360
}
@@ -1369,7 +1370,7 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve
13691370
} else {
13701371
LogPrint(BCLog::NET, "peer=%d: invalid header received\n", pfrom->GetId());
13711372
}
1372-
if (punish_duplicate_invalid && mapBlockIndex.find(first_invalid_header.GetHash()) != mapBlockIndex.end()) {
1373+
if (punish_duplicate_invalid && LookupBlockIndex(first_invalid_header.GetHash())) {
13731374
// Goal: don't allow outbound peers to use up our outbound
13741375
// connection slots if they are on incompatible chains.
13751376
//
@@ -2050,13 +2051,13 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
20502051

20512052
LOCK(cs_main);
20522053

2053-
BlockMap::iterator it = mapBlockIndex.find(req.blockhash);
2054-
if (it == mapBlockIndex.end() || !(it->second->nStatus & BLOCK_HAVE_DATA)) {
2054+
const CBlockIndex* pindex = LookupBlockIndex(req.blockhash);
2055+
if (!pindex || !(pindex->nStatus & BLOCK_HAVE_DATA)) {
20552056
LogPrint(BCLog::NET, "Peer %d sent us a getblocktxn for a block we don't have", pfrom->GetId());
20562057
return true;
20572058
}
20582059

2059-
if (it->second->nHeight < chainActive.Height() - MAX_BLOCKTXN_DEPTH) {
2060+
if (pindex->nHeight < chainActive.Height() - MAX_BLOCKTXN_DEPTH) {
20602061
// If an older block is requested (should never happen in practice,
20612062
// but can happen in tests) send a block response instead of a
20622063
// blocktxn response. Sending a full block response instead of a
@@ -2074,7 +2075,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
20742075
}
20752076

20762077
CBlock block;
2077-
bool ret = ReadBlockFromDisk(block, it->second, chainparams.GetConsensus());
2078+
bool ret = ReadBlockFromDisk(block, pindex, chainparams.GetConsensus());
20782079
assert(ret);
20792080

20802081
SendBlockTransactions(block, req, pfrom, connman);
@@ -2098,10 +2099,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
20982099
if (locator.IsNull())
20992100
{
21002101
// If locator is null, return the hashStop block
2101-
BlockMap::iterator mi = mapBlockIndex.find(hashStop);
2102-
if (mi == mapBlockIndex.end())
2102+
pindex = LookupBlockIndex(hashStop);
2103+
if (!pindex) {
21032104
return true;
2104-
pindex = (*mi).second;
2105+
}
21052106

21062107
if (!BlockRequestAllowed(pindex, chainparams.GetConsensus())) {
21072108
LogPrint(BCLog::NET, "%s: ignoring request from peer=%i for old block header that isn't in the main chain\n", __func__, pfrom->GetId());
@@ -2340,14 +2341,14 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
23402341
{
23412342
LOCK(cs_main);
23422343

2343-
if (mapBlockIndex.find(cmpctblock.header.hashPrevBlock) == mapBlockIndex.end()) {
2344+
if (!LookupBlockIndex(cmpctblock.header.hashPrevBlock)) {
23442345
// Doesn't connect (or is genesis), instead of DoSing in AcceptBlockHeader, request deeper headers
23452346
if (!IsInitialBlockDownload())
23462347
connman->PushMessage(pfrom, msgMaker.Make(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), uint256()));
23472348
return true;
23482349
}
23492350

2350-
if (mapBlockIndex.find(cmpctblock.header.GetHash()) == mapBlockIndex.end()) {
2351+
if (!LookupBlockIndex(cmpctblock.header.GetHash())) {
23512352
received_new_header = true;
23522353
}
23532354
}
@@ -3329,9 +3330,8 @@ bool PeerLogicValidation::SendMessages(CNode* pto, std::atomic<bool>& interruptM
33293330
// then send all headers past that one. If we come across any
33303331
// headers that aren't on chainActive, give up.
33313332
for (const uint256 &hash : pto->vBlockHashesToAnnounce) {
3332-
BlockMap::iterator mi = mapBlockIndex.find(hash);
3333-
assert(mi != mapBlockIndex.end());
3334-
const CBlockIndex *pindex = mi->second;
3333+
const CBlockIndex* pindex = LookupBlockIndex(hash);
3334+
assert(pindex);
33353335
if (chainActive[pindex->nHeight] != pindex) {
33363336
// Bail out if we reorged away from this block
33373337
fRevertToInv = true;
@@ -3422,9 +3422,8 @@ bool PeerLogicValidation::SendMessages(CNode* pto, std::atomic<bool>& interruptM
34223422
// in the past.
34233423
if (!pto->vBlockHashesToAnnounce.empty()) {
34243424
const uint256 &hashToAnnounce = pto->vBlockHashesToAnnounce.back();
3425-
BlockMap::iterator mi = mapBlockIndex.find(hashToAnnounce);
3426-
assert(mi != mapBlockIndex.end());
3427-
const CBlockIndex *pindex = mi->second;
3425+
const CBlockIndex* pindex = LookupBlockIndex(hashToAnnounce);
3426+
assert(pindex);
34283427

34293428
// Warn if we're announcing a block that is not on the main chain.
34303429
// This should be very rare and could be optimized out.

src/qt/transactionrecord.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
167167
// Determine transaction status
168168

169169
// Find the block the tx is in
170-
CBlockIndex* pindex = nullptr;
171-
BlockMap::iterator mi = mapBlockIndex.find(wtx.hashBlock);
172-
if (mi != mapBlockIndex.end())
173-
pindex = (*mi).second;
170+
const CBlockIndex* pindex = LookupBlockIndex(wtx.hashBlock);
174171

175172
// Sort order, unrecorded transactions sort to the top
176173
status.sortKey = strprintf("%010d-%01d-%010u-%03d",

src/rest.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,7 @@ static bool rest_headers(HTTPRequest* req,
147147
headers.reserve(count);
148148
{
149149
LOCK(cs_main);
150-
BlockMap::const_iterator it = mapBlockIndex.find(hash);
151-
const CBlockIndex *pindex = (it != mapBlockIndex.end()) ? it->second : nullptr;
150+
const CBlockIndex* pindex = LookupBlockIndex(hash);
152151
while (pindex != nullptr && chainActive.Contains(pindex)) {
153152
headers.push_back(pindex);
154153
if (headers.size() == (unsigned long)count)
@@ -212,10 +211,11 @@ static bool rest_block(HTTPRequest* req,
212211
CBlockIndex* pblockindex = nullptr;
213212
{
214213
LOCK(cs_main);
215-
if (mapBlockIndex.count(hash) == 0)
214+
pblockindex = LookupBlockIndex(hash);
215+
if (!pblockindex) {
216216
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
217+
}
217218

218-
pblockindex = mapBlockIndex[hash];
219219
if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
220220
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not available (pruned data)");
221221

0 commit comments

Comments
 (0)