Merge ef29d5d7e2 into merged_master (Bitcoin PR bitcoin/bitcoin#27607)

This commit is contained in:
Byron Hambly 2025-07-01 11:32:01 +02:00
commit f61ec91393
20 changed files with 189 additions and 110 deletions

View file

@ -129,13 +129,12 @@ using node::CalculateCacheSizes;
using node::DEFAULT_PERSIST_MEMPOOL;
using node::DEFAULT_PRINTPRIORITY;
using node::fReindex;
using node::g_indexes_ready_to_sync;
using node::KernelNotifications;
using node::LoadChainstate;
using node::MempoolPath;
using node::NodeContext;
using node::ShouldPersistMempool;
using node::ThreadImport;
using node::ImportBlocks;
using node::VerifyLoadedChainstate;
static constexpr bool DEFAULT_PROXYRANDOMIZE{true};
@ -277,7 +276,7 @@ void Shutdown(NodeContext& node)
// CScheduler/checkqueue, scheduler and load block thread.
if (node.scheduler) node.scheduler->stop();
if (node.reverification_scheduler) node.reverification_scheduler->stop();
if (node.chainman && node.chainman->m_load_block.joinable()) node.chainman->m_load_block.join();
if (node.chainman && node.chainman->m_thread_load.joinable()) node.chainman->m_thread_load.join();
StopScriptCheckWorkerThreads();
// After the threads that potentially access these pointers have been stopped,
@ -1687,8 +1686,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
// ********************************************************* Step 8: start indexers
// If reindex-chainstate was specified, delay syncing indexes until ThreadImport has reindexed the chain
if (!fReindexChainState) g_indexes_ready_to_sync = true;
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
auto result{WITH_LOCK(cs_main, return CheckLegacyTxindex(*Assert(chainman.m_blockman.m_block_tree_db)))};
if (!result) {
@ -1696,25 +1693,22 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
}
g_txindex = std::make_unique<TxIndex>(interfaces::MakeChain(node), cache_sizes.tx_index, false, fReindex);
if (!g_txindex->Start()) {
return false;
}
node.indexes.emplace_back(g_txindex.get());
}
for (const auto& filter_type : g_enabled_filter_types) {
InitBlockFilterIndex([&]{ return interfaces::MakeChain(node); }, filter_type, cache_sizes.filter_index, false, fReindex);
if (!GetBlockFilterIndex(filter_type)->Start()) {
return false;
}
node.indexes.emplace_back(GetBlockFilterIndex(filter_type));
}
if (args.GetBoolArg("-coinstatsindex", DEFAULT_COINSTATSINDEX)) {
g_coin_stats_index = std::make_unique<CoinStatsIndex>(interfaces::MakeChain(node), /*cache_size=*/0, false, fReindex);
if (!g_coin_stats_index->Start()) {
return false;
}
node.indexes.emplace_back(g_coin_stats_index.get());
}
// Init indexes
for (auto index : node.indexes) if (!index->Init()) return false;
// ********************************************************* Step 9: load wallet
for (const auto& client : node.chain_clients) {
if (!client->load()) {
@ -1798,15 +1792,24 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
vImportFiles.push_back(fs::PathFromString(strFile));
}
chainman.m_load_block = std::thread(&util::TraceThread, "loadblk", [=, &chainman, &args] {
ThreadImport(chainman, vImportFiles, ShouldPersistMempool(args) ? MempoolPath(args) : fs::path{});
chainman.m_thread_load = std::thread(&util::TraceThread, "initload", [=, &chainman, &args, &node] {
// Import blocks
ImportBlocks(chainman, vImportFiles);
// Start indexes initial sync
if (!StartIndexBackgroundSync(node)) {
bilingual_str err_str = _("Failed to start indexes, shutting down..");
chainman.GetNotifications().fatalError(err_str.original, err_str);
return;
}
// Load mempool from disk
chainman.ActiveChainstate().LoadMempool(ShouldPersistMempool(args) ? MempoolPath(args) : fs::path{});
});
// Wait for genesis block to be processed
{
WAIT_LOCK(g_genesis_wait_mutex, lock);
// We previously could hang here if StartShutdown() is called prior to
// ThreadImport getting started, so instead we just wait on a timer to
// ImportBlocks getting started, so instead we just wait on a timer to
// check ShutdownRequested() regularly.
while (!fHaveGenesis && !ShutdownRequested()) {
g_genesis_wait_cv.wait_for(lock, std::chrono::milliseconds(500));
@ -2059,3 +2062,47 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
return true;
}
bool StartIndexBackgroundSync(NodeContext& node)
{
// Find the oldest block among all indexes.
// This block is used to verify that we have the required blocks' data stored on disk,
// starting from that point up to the current tip.
// indexes_start_block='nullptr' means "start from height 0".
std::optional<const CBlockIndex*> indexes_start_block;
std::string older_index_name;
ChainstateManager& chainman = *Assert(node.chainman);
for (auto index : node.indexes) {
const IndexSummary& summary = index->GetSummary();
if (summary.synced) continue;
// Get the last common block between the index best block and the active chain
LOCK(::cs_main);
const CChain& active_chain = chainman.ActiveChain();
const CBlockIndex* pindex = chainman.m_blockman.LookupBlockIndex(summary.best_block_hash);
if (!active_chain.Contains(pindex)) {
pindex = active_chain.FindFork(pindex);
}
if (!indexes_start_block || !pindex || pindex->nHeight < indexes_start_block.value()->nHeight) {
indexes_start_block = pindex;
older_index_name = summary.name;
if (!pindex) break; // Starting from genesis so no need to look for earlier block.
}
};
// Verify all blocks needed to sync to current tip are present.
if (indexes_start_block) {
LOCK(::cs_main);
const CBlockIndex* start_block = *indexes_start_block;
if (!start_block) start_block = chainman.ActiveChain().Genesis();
if (!chainman.m_blockman.CheckBlockDataAvailability(*chainman.ActiveChain().Tip(), *Assert(start_block))) {
return InitError(strprintf(Untranslated("%s best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)"), older_index_name));
}
}
// Start threads
for (auto index : node.indexes) if (!index->StartBackgroundSync()) return false;
return true;
}