Skip to content

Commit dd065da

Browse files
hebastoLarryRuane
andcommitted
refactor: Make mapBlocksUnknownParent local, and rename it
Co-authored-by: Larry Ruane <[email protected]>
1 parent f002f8a commit dd065da

File tree

4 files changed

+60
-12
lines changed

4 files changed

+60
-12
lines changed

src/node/blockstorage.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <util/system.h>
2222
#include <validation.h>
2323

24+
#include <map>
2425
#include <unordered_map>
2526

2627
namespace node {
@@ -834,6 +835,9 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
834835
// -reindex
835836
if (fReindex) {
836837
int nFile = 0;
838+
// Map of disk positions for blocks with unknown parent (only used for reindex);
839+
// parent hash -> child disk position, multiple children can have the same parent.
840+
std::multimap<uint256, FlatFilePos> blocks_with_unknown_parent;
837841
while (true) {
838842
FlatFilePos pos(nFile, 0);
839843
if (!fs::exists(GetBlockPosFilename(pos))) {
@@ -844,7 +848,7 @@ void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImportFile
844848
break; // This error is logged in OpenBlockFile
845849
}
846850
LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile);
847-
chainman.ActiveChainstate().LoadExternalBlockFile(file, &pos);
851+
chainman.ActiveChainstate().LoadExternalBlockFile(file, &pos, &blocks_with_unknown_parent);
848852
if (ShutdownRequested()) {
849853
LogPrintf("Shutdown requested. Exit %s\n", __func__);
850854
return;

src/test/fuzz/load_external_block_file.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ FUZZ_TARGET_INIT(load_external_block_file, initialize_load_external_block_file)
3131
if (fuzzed_block_file == nullptr) {
3232
return;
3333
}
34-
FlatFilePos flat_file_pos;
35-
g_setup->m_node.chainman->ActiveChainstate().LoadExternalBlockFile(fuzzed_block_file, fuzzed_data_provider.ConsumeBool() ? &flat_file_pos : nullptr);
34+
if (fuzzed_data_provider.ConsumeBool()) {
35+
// Corresponds to the -reindex case (track orphan blocks across files).
36+
FlatFilePos flat_file_pos;
37+
std::multimap<uint256, FlatFilePos> blocks_with_unknown_parent;
38+
g_setup->m_node.chainman->ActiveChainstate().LoadExternalBlockFile(fuzzed_block_file, &flat_file_pos, &blocks_with_unknown_parent);
39+
} else {
40+
// Corresponds to the -loadblock= case (orphan blocks aren't tracked across files).
41+
g_setup->m_node.chainman->ActiveChainstate().LoadExternalBlockFile(fuzzed_block_file);
42+
}
3643
}

src/validation.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include <warnings.h>
5858

5959
#include <algorithm>
60+
#include <cassert>
6061
#include <chrono>
6162
#include <deque>
6263
#include <numeric>
@@ -4261,11 +4262,16 @@ bool CChainState::LoadGenesisBlock()
42614262
return true;
42624263
}
42634264

4264-
void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
4265+
void CChainState::LoadExternalBlockFile(
4266+
FILE* fileIn,
4267+
FlatFilePos* dbp,
4268+
std::multimap<uint256, FlatFilePos>* blocks_with_unknown_parent)
42654269
{
42664270
AssertLockNotHeld(m_chainstate_mutex);
4267-
// Map of disk positions for blocks with unknown parent (only used for reindex)
4268-
static std::multimap<uint256, FlatFilePos> mapBlocksUnknownParent;
4271+
4272+
// Either both should be specified (-reindex), or neither (-loadblock).
4273+
assert(!dbp == !blocks_with_unknown_parent);
4274+
42694275
int64_t nStart = GetTimeMillis();
42704276

42714277
int nLoaded = 0;
@@ -4315,8 +4321,9 @@ void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
43154321
if (hash != m_params.GetConsensus().hashGenesisBlock && !m_blockman.LookupBlockIndex(block.hashPrevBlock)) {
43164322
LogPrint(BCLog::REINDEX, "%s: Out of order block %s, parent %s not known\n", __func__, hash.ToString(),
43174323
block.hashPrevBlock.ToString());
4318-
if (dbp)
4319-
mapBlocksUnknownParent.insert(std::make_pair(block.hashPrevBlock, *dbp));
4324+
if (dbp && blocks_with_unknown_parent) {
4325+
blocks_with_unknown_parent->emplace(block.hashPrevBlock, *dbp);
4326+
}
43204327
continue;
43214328
}
43224329

@@ -4345,13 +4352,15 @@ void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
43454352

43464353
NotifyHeaderTip(*this);
43474354

4355+
if (!blocks_with_unknown_parent) continue;
4356+
43484357
// Recursively process earlier encountered successors of this block
43494358
std::deque<uint256> queue;
43504359
queue.push_back(hash);
43514360
while (!queue.empty()) {
43524361
uint256 head = queue.front();
43534362
queue.pop_front();
4354-
std::pair<std::multimap<uint256, FlatFilePos>::iterator, std::multimap<uint256, FlatFilePos>::iterator> range = mapBlocksUnknownParent.equal_range(head);
4363+
auto range = blocks_with_unknown_parent->equal_range(head);
43554364
while (range.first != range.second) {
43564365
std::multimap<uint256, FlatFilePos>::iterator it = range.first;
43574366
std::shared_ptr<CBlock> pblockrecursive = std::make_shared<CBlock>();
@@ -4366,7 +4375,7 @@ void CChainState::LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp)
43664375
}
43674376
}
43684377
range.first++;
4369-
mapBlocksUnknownParent.erase(it);
4378+
blocks_with_unknown_parent->erase(it);
43704379
NotifyHeaderTip(*this);
43714380
}
43724381
}

src/validation.h

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -575,8 +575,36 @@ class CChainState
575575
bool ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
576576
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
577577

578-
/** Import blocks from an external file */
579-
void LoadExternalBlockFile(FILE* fileIn, FlatFilePos* dbp = nullptr)
578+
/**
579+
* Import blocks from an external file
580+
*
581+
* During reindexing, this function is called for each block file (datadir/blocks/blk?????.dat).
582+
* It reads all blocks contained in the given file and attempts to process them (add them to the
583+
* block index). The blocks may be out of order within each file and across files. Often this
584+
* function reads a block but finds that its parent hasn't been read yet, so the block can't be
585+
* processed yet. The function will add an entry to the blocks_with_unknown_parent map (which is
586+
* passed as an argument), so that when the block's parent is later read and processed, this
587+
* function can re-read the child block from disk and process it.
588+
*
589+
* Because a block's parent may be in a later file, not just later in the same file, the
590+
* blocks_with_unknown_parent map must be passed in and out with each call. It's a multimap,
591+
* rather than just a map, because multiple blocks may have the same parent (when chain splits
592+
* or stale blocks exist). It maps from parent-hash to child-disk-position.
593+
*
594+
* This function can also be used to read blocks from user-specified block files using the
595+
* -loadblock= option. There's no unknown-parent tracking, so the last two arguments are omitted.
596+
*
597+
*
598+
* @param[in] fileIn FILE handle to file containing blocks to read
599+
* @param[in] dbp (optional) Disk block position (only for reindex)
600+
* @param[in,out] blocks_with_unknown_parent (optional) Map of disk positions for blocks with
601+
* unknown parent, key is parent block hash
602+
* (only used for reindex)
603+
* */
604+
void LoadExternalBlockFile(
605+
FILE* fileIn,
606+
FlatFilePos* dbp = nullptr,
607+
std::multimap<uint256, FlatFilePos>* blocks_with_unknown_parent = nullptr)
580608
EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex);
581609

582610
/**

0 commit comments

Comments
 (0)