diff --git a/src/Makefile.am b/src/Makefile.am index a72d1d758d..fb897c43f9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -247,6 +247,7 @@ BITCOIN_CORE_H = \ netbase.h \ netfulfilledman.h \ netmessagemaker.h \ + node/blockstorage.h \ node/coin.h \ node/coinstats.h \ node/context.h \ @@ -441,6 +442,7 @@ libbitcoin_server_a_SOURCES = \ net.cpp \ netfulfilledman.cpp \ net_processing.cpp \ + node/blockstorage.cpp \ node/coin.cpp \ node/coinstats.cpp \ node/context.cpp \ diff --git a/src/evo/cbtx.cpp b/src/evo/cbtx.cpp index 34797da333..42df4fee37 100644 --- a/src/evo/cbtx.cpp +++ b/src/evo/cbtx.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/src/evo/creditpool.cpp b/src/evo/creditpool.cpp index dda04ad8f1..14f7609a77 100644 --- a/src/evo/creditpool.cpp +++ b/src/evo/creditpool.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff --git a/src/evo/simplifiedmns.cpp b/src/evo/simplifiedmns.cpp index 481f77a077..e17f071ccd 100644 --- a/src/evo/simplifiedmns.cpp +++ b/src/evo/simplifiedmns.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include diff --git a/src/index/base.cpp b/src/index/base.cpp index d95953614a..623b4f438d 100644 --- a/src/index/base.cpp +++ b/src/index/base.cpp @@ -4,11 +4,12 @@ #include #include +#include #include #include #include #include -#include +#include // For g_chainman #include constexpr char DB_BEST_BLOCK = 'B'; diff --git a/src/index/blockfilterindex.cpp b/src/index/blockfilterindex.cpp index 2b6e4b7ef7..4152dfee5a 100644 --- a/src/index/blockfilterindex.cpp +++ b/src/index/blockfilterindex.cpp @@ -6,9 +6,8 @@ #include #include +#include #include -#include -#include /* The index database stores three items for each block: the disk location of the encoded filter, * its dSHA256 hash, and the header. Those belonging to blocks on the active chain are indexed by diff --git a/src/init.cpp b/src/init.cpp index dae3cb528e..abf2645e08 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -36,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -123,7 +123,6 @@ static const bool DEFAULT_PROXYRANDOMIZE = true; static const bool DEFAULT_REST_ENABLE = false; -static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false; static CDSNotificationInterface* pdsNotificationInterface = nullptr; @@ -189,8 +188,6 @@ static fs::path GetPidFile(const ArgsManager& args) static std::unique_ptr globalVerifyHandle; -static std::thread g_load_block; - void Interrupt(NodeContext& node) { InterruptHTTPServer(); @@ -266,7 +263,7 @@ void PrepareShutdown(NodeContext& node) // After everything has been shut down, but before things get flushed, stop the // CScheduler/checkqueue, threadGroup and load block thread. if (node.scheduler) node.scheduler->stop(); - if (g_load_block.joinable()) g_load_block.join(); + if (node.chainman && node.chainman->m_load_block.joinable()) node.chainman->m_load_block.join(); StopScriptCheckWorkerThreads(); // After there are no more peers/RPC left to give us new data which may generate @@ -825,20 +822,6 @@ static void BlockNotifyGenesisWait(bool, const CBlockIndex *pBlockIndex) } } -struct CImportingNow -{ - CImportingNow() { - assert(fImporting == false); - fImporting = true; - } - - ~CImportingNow() { - assert(fImporting == true); - fImporting = false; - } -}; - - // If we're using -prune with -reindex, then delete block files that will be ignored by the // reindex. Since reindexing works by starting at block file 0 and looping until a blockfile // is missing, do the same here to delete any later block files after a gap. Also delete all @@ -880,103 +863,6 @@ static void CleanupBlockRevFiles() } } -static void ThreadImport(ChainstateManager& chainman, std::vector vImportFiles, const ArgsManager& args) -{ - ScheduleBatchPriority(); - - { - CImportingNow imp; - - // -reindex - if (fReindex) { - int nFile = 0; - while (true) { - FlatFilePos pos(nFile, 0); - if (!fs::exists(GetBlockPosFilename(pos))) - break; // No block files left to reindex - FILE *file = OpenBlockFile(pos, true); - if (!file) - break; // This error is logged in OpenBlockFile - LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile); - ::ChainstateActive().LoadExternalBlockFile(file, &pos); - if (ShutdownRequested()) { - LogPrintf("Shutdown requested. Exit %s\n", __func__); - return; - } - nFile++; - } - pblocktree->WriteReindexing(false); - fReindex = false; - LogPrintf("Reindexing finished\n"); - // To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked): - ::ChainstateActive().LoadGenesisBlock(); - } - - // -loadblock= - for (const fs::path& path : vImportFiles) { - FILE *file = fsbridge::fopen(path, "rb"); - if (file) { - LogPrintf("Importing blocks file %s...\n", path.string()); - ::ChainstateActive().LoadExternalBlockFile(file); - if (ShutdownRequested()) { - LogPrintf("Shutdown requested. Exit %s\n", __func__); - return; - } - } else { - LogPrintf("Warning: Could not open blocks file %s\n", path.string()); - } - } - - // scan for better chains in the block chain database, that are not yet connected in the active best chain - - // We can't hold cs_main during ActivateBestChain even though we're accessing - // the chainman unique_ptrs since ABC requires us not to be holding cs_main, so retrieve - // the relevant pointers before the ABC call. - for (CChainState* chainstate : WITH_LOCK(::cs_main, return chainman.GetAll())) { - BlockValidationState state; - if (!chainstate->ActivateBestChain(state, nullptr)) { - LogPrintf("Failed to connect best block (%s)\n", state.ToString()); - StartShutdown(); - return; - } - } - - if (args.GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) { - LogPrintf("Stopping after block import\n"); - StartShutdown(); - return; - } - } // End scope of CImportingNow - - // force UpdatedBlockTip to initialize nCachedBlockHeight for DS, MN payments and budgets - // but don't call it directly to prevent triggering of other listeners like zmq etc. - // GetMainSignals().UpdatedBlockTip(::ChainActive().Tip()); - pdsNotificationInterface->InitializeCurrentBlockTip(); - - { - // Get all UTXOs for each MN collateral in one go so that we can fill coin cache early - // and reduce further locking overhead for cs_main in other parts of code including GUI - LogPrintf("Filling coin cache with masternode UTXOs...\n"); - LOCK(cs_main); - int64_t nStart = GetTimeMillis(); - auto mnList = deterministicMNManager->GetListAtChainTip(); - mnList.ForEachMN(false, [&](auto& dmn) { - Coin coin; - GetUTXOCoin(dmn.collateralOutpoint, coin); - }); - LogPrintf("Filling coin cache with masternode UTXOs: done in %dms\n", GetTimeMillis() - nStart); - } - - if (fMasternodeMode) { - assert(activeMasternodeManager); - activeMasternodeManager->Init(::ChainActive().Tip()); - } - - g_wallet_init_interface.AutoLockMasternodeCollaterals(); - - chainman.ActiveChainstate().LoadMempool(args); -} - static void PeriodicStats(ArgsManager& args, const CTxMemPool& mempool) { assert(args.GetBoolArg("-statsenabled", DEFAULT_STATSD_ENABLE)); @@ -2468,7 +2354,9 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc vImportFiles.push_back(strFile); } - g_load_block = std::thread(&TraceThread>, "loadblk", [=, &chainman, &args]{ ThreadImport(chainman, vImportFiles, args); }); + chainman.m_load_block = std::thread(&TraceThread>, "loadblk", [=, &chainman, &args] { + ThreadImport(chainman, *pdsNotificationInterface ,vImportFiles, args); + }); // Wait for genesis block to be processed { diff --git a/src/llmq/blockprocessor.cpp b/src/llmq/blockprocessor.cpp index 4a4a2c34b2..8ad2c70425 100644 --- a/src/llmq/blockprocessor.cpp +++ b/src/llmq/blockprocessor.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/src/llmq/chainlocks.cpp b/src/llmq/chainlocks.cpp index d6c9f147ad..f6ce0e61d3 100644 --- a/src/llmq/chainlocks.cpp +++ b/src/llmq/chainlocks.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/src/net_processing.cpp b/src/net_processing.cpp index a53d9ee917..78344eaeec 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff --git a/src/node/README.md b/src/node/README.md index e99a717534..ab5979594d 100644 --- a/src/node/README.md +++ b/src/node/README.md @@ -15,8 +15,7 @@ As a rule of thumb, code in one of the [`src/node/`](./), calling code in the other directories directly, and only invoke it indirectly through the more limited [`src/interfaces/`](../interfaces/) classes. -The [`src/node/`](./) directory is a new directory introduced in -[#14978](https://github.com/bitcoin/bitcoin/pull/14978) and at the moment is +This directory is at the moment sparsely populated. Eventually more substantial files like [`src/validation.cpp`](../validation.cpp) and [`src/txmempool.cpp`](../txmempool.cpp) might be moved there. diff --git a/src/node/blockstorage.cpp b/src/node/blockstorage.cpp new file mode 100644 index 0000000000..9d92daf199 --- /dev/null +++ b/src/node/blockstorage.cpp @@ -0,0 +1,223 @@ +// Copyright (c) 2011-2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// From validation. TODO move here +bool FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigned int nHeight, CChain& active_chain, uint64_t nTime, bool fKnown = false); + +static bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos, const CMessageHeader::MessageStartChars& messageStart) +{ + // Open history file to append + CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION); + if (fileout.IsNull()) { + return error("WriteBlockToDisk: OpenBlockFile failed"); + } + + // Write index header + unsigned int nSize = GetSerializeSize(block, fileout.GetVersion()); + fileout << messageStart << nSize; + + // Write block + long fileOutPos = ftell(fileout.Get()); + if (fileOutPos < 0) { + return error("WriteBlockToDisk: ftell failed"); + } + pos.nPos = (unsigned int)fileOutPos; + fileout << block; + + return true; +} + +bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::Params& consensusParams) +{ + block.SetNull(); + + // Open history file to read + CAutoFile filein(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION); + if (filein.IsNull()) { + return error("ReadBlockFromDisk: OpenBlockFile failed for %s", pos.ToString()); + } + + // Read block + try { + filein >> block; + } catch (const std::exception& e) { + return error("%s: Deserialize or I/O error - %s at %s", __func__, e.what(), pos.ToString()); + } + + // Check the header + if (!CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) { + return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString()); + } + + return true; +} + +bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams) +{ + FlatFilePos blockPos; + { + LOCK(cs_main); + blockPos = pindex->GetBlockPos(); + } + + if (!ReadBlockFromDisk(block, blockPos, consensusParams)) { + return false; + } + if (block.GetHash() != pindex->GetBlockHash()) { + return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s", + pindex->ToString(), pindex->GetBlockPos().ToString()); + } + return true; +} + +/** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */ +FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const CChainParams& chainparams, const FlatFilePos* dbp) +{ + unsigned int nBlockSize = ::GetSerializeSize(block, CLIENT_VERSION); + FlatFilePos blockPos; + if (dbp != nullptr) { + blockPos = *dbp; + } + if (!FindBlockPos(blockPos, nBlockSize + 8, nHeight, active_chain, block.GetBlockTime(), dbp != nullptr)) { + error("%s: FindBlockPos failed", __func__); + return FlatFilePos(); + } + if (dbp == nullptr) { + if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) { + AbortNode("Failed to write block"); + return FlatFilePos(); + } + } + return blockPos; +} + +struct CImportingNow { + CImportingNow() + { + assert(fImporting == false); + fImporting = true; + } + + ~CImportingNow() + { + assert(fImporting == true); + fImporting = false; + } +}; + +void ThreadImport(ChainstateManager& chainman, CDSNotificationInterface& dsnfi, std::vector vImportFiles, const ArgsManager& args) +{ + ScheduleBatchPriority(); + + { + CImportingNow imp; + + // -reindex + if (fReindex) { + int nFile = 0; + while (true) { + FlatFilePos pos(nFile, 0); + if (!fs::exists(GetBlockPosFilename(pos))) { + break; // No block files left to reindex + } + FILE* file = OpenBlockFile(pos, true); + if (!file) { + break; // This error is logged in OpenBlockFile + } + LogPrintf("Reindexing block file blk%05u.dat...\n", (unsigned int)nFile); + chainman.ActiveChainstate().LoadExternalBlockFile(file, &pos); + if (ShutdownRequested()) { + LogPrintf("Shutdown requested. Exit %s\n", __func__); + return; + } + nFile++; + } + pblocktree->WriteReindexing(false); + fReindex = false; + LogPrintf("Reindexing finished\n"); + // To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked): + chainman.ActiveChainstate().LoadGenesisBlock(); + } + + // -loadblock= + for (const fs::path& path : vImportFiles) { + FILE *file = fsbridge::fopen(path, "rb"); + if (file) { + LogPrintf("Importing blocks file %s...\n", path.string()); + chainman.ActiveChainstate().LoadExternalBlockFile(file); + if (ShutdownRequested()) { + LogPrintf("Shutdown requested. Exit %s\n", __func__); + return; + } + } else { + LogPrintf("Warning: Could not open blocks file %s\n", path.string()); + } + } + + // scan for better chains in the block chain database, that are not yet connected in the active best chain + + // We can't hold cs_main during ActivateBestChain even though we're accessing + // the chainman unique_ptrs since ABC requires us not to be holding cs_main, so retrieve + // the relevant pointers before the ABC call. + for (CChainState* chainstate : WITH_LOCK(::cs_main, return chainman.GetAll())) { + BlockValidationState state; + if (!chainstate->ActivateBestChain(state, nullptr)) { + LogPrintf("Failed to connect best block (%s)\n", state.ToString()); + StartShutdown(); + return; + } + } + + if (args.GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) { + LogPrintf("Stopping after block import\n"); + StartShutdown(); + return; + } + } // End scope of CImportingNow + + // force UpdatedBlockTip to initialize nCachedBlockHeight for DS, MN payments and budgets + // but don't call it directly to prevent triggering of other listeners like zmq etc. + // GetMainSignals().UpdatedBlockTip(::ChainActive().Tip()); + dsnfi.InitializeCurrentBlockTip(); + + { + // Get all UTXOs for each MN collateral in one go so that we can fill coin cache early + // and reduce further locking overhead for cs_main in other parts of code including GUI + LogPrintf("Filling coin cache with masternode UTXOs...\n"); + LOCK(cs_main); + int64_t nStart = GetTimeMillis(); + auto mnList = deterministicMNManager->GetListAtChainTip(); + mnList.ForEachMN(false, [&](auto& dmn) { + Coin coin; + GetUTXOCoin(dmn.collateralOutpoint, coin); + }); + LogPrintf("Filling coin cache with masternode UTXOs: done in %dms\n", GetTimeMillis() - nStart); + } + + if (fMasternodeMode) { + assert(activeMasternodeManager); + activeMasternodeManager->Init(::ChainActive().Tip()); + } + + g_wallet_init_interface.AutoLockMasternodeCollaterals(); + + chainman.ActiveChainstate().LoadMempool(args); +} diff --git a/src/node/blockstorage.h b/src/node/blockstorage.h new file mode 100644 index 0000000000..bfd35ba32b --- /dev/null +++ b/src/node/blockstorage.h @@ -0,0 +1,39 @@ +// Copyright (c) 2011-2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_NODE_BLOCKSTORAGE_H +#define BITCOIN_NODE_BLOCKSTORAGE_H + +#include +#include + +#include +#include // For CMessageHeader::MessageStartChars + +class ArgsManager; +class CBlock; +class CBlockIndex; +class CBlockUndo; +class CChain; +class CChainParams; +class CDSNotificationInterface; +class ChainstateManager; +struct FlatFilePos; +namespace Consensus { +struct Params; +} + +static constexpr bool DEFAULT_STOPAFTERBLOCKIMPORT{false}; + +/** Functions for disk access for blocks */ +bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::Params& consensusParams); +bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams); + +bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex); + +FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const CChainParams& chainparams, const FlatFilePos* dbp); + +void ThreadImport(ChainstateManager& chainman, CDSNotificationInterface& dsnfi, std::vector vImportFiles, const ArgsManager& args); + +#endif // BITCOIN_NODE_BLOCKSTORAGE_H diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index b44329a95b..f7e2056895 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include diff --git a/src/rest.cpp b/src/rest.cpp index c615a4900a..a69f4605ee 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 19d82888ed..8346c7500c 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/src/rpc/masternode.cpp b/src/rpc/masternode.cpp index 6ac2c84410..7840e089af 100644 --- a/src/rpc/masternode.cpp +++ b/src/rpc/masternode.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index a696d9555a..07482192e2 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/src/shutdown.cpp b/src/shutdown.cpp index 998328e377..f835833f38 100644 --- a/src/shutdown.cpp +++ b/src/shutdown.cpp @@ -5,6 +5,10 @@ #include +#include +#include +#include + #include #include @@ -17,6 +21,18 @@ #include #endif +bool AbortNode(const std::string& strMessage, bilingual_str user_message) +{ + SetMiscWarning(strMessage); + LogPrintf("*** %s\n", strMessage); + if (user_message.empty()) { + user_message = _("A fatal internal error occurred, see debug.log for details"); + } + AbortError(user_message); + StartShutdown(); + return false; +} + static std::atomic fRequestShutdown(false); static std::atomic fRequestRestart(false); diff --git a/src/shutdown.h b/src/shutdown.h index 6819dc6e1a..3970484657 100644 --- a/src/shutdown.h +++ b/src/shutdown.h @@ -6,6 +6,11 @@ #ifndef BITCOIN_SHUTDOWN_H #define BITCOIN_SHUTDOWN_H +#include // For bilingual_str + +/** Abort with a message */ +bool AbortNode(const std::string& strMessage, bilingual_str user_message = bilingual_str{}); + /** Initialize shutdown state. This must be called before using either StartShutdown(), * AbortShutdown() or WaitForShutdown(). Calling ShutdownRequested() is always safe. */ diff --git a/src/test/util/blockfilter.cpp b/src/test/util/blockfilter.cpp index cbc95d8bdc..d1f0cad7cc 100644 --- a/src/test/util/blockfilter.cpp +++ b/src/test/util/blockfilter.cpp @@ -5,6 +5,7 @@ #include #include +#include #include bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex* block_index, BlockFilter& filter) diff --git a/src/validation.cpp b/src/validation.cpp index 3fed42e444..add1602cc5 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -1087,72 +1088,6 @@ CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMe return nullptr; } -////////////////////////////////////////////////////////////////////////////// -// -// CBlock and CBlockIndex -// - -static bool WriteBlockToDisk(const CBlock& block, FlatFilePos& pos, const CMessageHeader::MessageStartChars& messageStart) -{ - // Open history file to append - CAutoFile fileout(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION); - if (fileout.IsNull()) - return error("WriteBlockToDisk: OpenBlockFile failed"); - - // Write index header - unsigned int nSize = GetSerializeSize(block, fileout.GetVersion()); - fileout << messageStart << nSize; - - // Write block - long fileOutPos = ftell(fileout.Get()); - if (fileOutPos < 0) - return error("WriteBlockToDisk: ftell failed"); - pos.nPos = (unsigned int)fileOutPos; - fileout << block; - - return true; -} - -bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::Params& consensusParams) -{ - block.SetNull(); - - // Open history file to read - CAutoFile filein(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION); - if (filein.IsNull()) - return error("ReadBlockFromDisk: OpenBlockFile failed for %s", pos.ToString()); - - // Read block - try { - filein >> block; - } - catch (const std::exception& e) { - return error("%s: Deserialize or I/O error - %s at %s", __func__, e.what(), pos.ToString()); - } - - // Check the header - if (!CheckProofOfWork(block.GetHash(), block.nBits, consensusParams)) - return error("ReadBlockFromDisk: Errors in block header at %s", pos.ToString()); - - return true; -} - -bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams) -{ - FlatFilePos blockPos; - { - LOCK(cs_main); - blockPos = pindex->GetBlockPos(); - } - - if (!ReadBlockFromDisk(block, blockPos, consensusParams)) - return false; - if (block.GetHash() != pindex->GetBlockHash()) - return error("ReadBlockFromDisk(CBlock&, CBlockIndex*): GetHash() doesn't match index for %s at %s", - pindex->ToString(), pindex->GetBlockPos().ToString()); - return true; -} - double ConvertBitsToDouble(unsigned int nBits) { int nShift = (nBits >> 24) & 0xff; @@ -1676,19 +1611,6 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex) return true; } -/** Abort with a message */ -static bool AbortNode(const std::string& strMessage, bilingual_str user_message = bilingual_str()) -{ - SetMiscWarning(strMessage); - LogPrintf("*** %s\n", strMessage); - if (user_message.empty()) { - user_message = _("A fatal internal error occurred, see debug.log for details"); - } - AbortError(user_message); - StartShutdown(); - return false; -} - static bool AbortNode(BlockValidationState& state, const std::string& strMessage, const bilingual_str& userMessage = bilingual_str()) { AbortNode(strMessage, userMessage); @@ -3759,7 +3681,8 @@ void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pi } } -static bool FindBlockPos(FlatFilePos &pos, unsigned int nAddSize, unsigned int nHeight, CChain& active_chain, uint64_t nTime, bool fKnown = false) +// TODO move to blockstorage +bool FindBlockPos(FlatFilePos& pos, unsigned int nAddSize, unsigned int nHeight, CChain& active_chain, uint64_t nTime, bool fKnown = false) { LOCK(cs_LastBlockFile); @@ -4224,25 +4147,6 @@ bool ChainstateManager::ProcessNewBlockHeaders(const std::vector& return true; } -/** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */ -static FlatFilePos SaveBlockToDisk(const CBlock& block, int nHeight, CChain& active_chain, const CChainParams& chainparams, const FlatFilePos* dbp) { - unsigned int nBlockSize = ::GetSerializeSize(block, CLIENT_VERSION); - FlatFilePos blockPos; - if (dbp != nullptr) - blockPos = *dbp; - if (!FindBlockPos(blockPos, nBlockSize+8, nHeight, active_chain, block.GetBlockTime(), dbp != nullptr)) { - error("%s: FindBlockPos failed", __func__); - return FlatFilePos(); - } - if (dbp == nullptr) { - if (!WriteBlockToDisk(block, blockPos, chainparams.MessageStart())) { - AbortNode("Failed to write block"); - return FlatFilePos(); - } - } - return blockPos; -} - /** Store block on disk. If dbp is non-nullptr, the file is known to already reside on disk */ bool CChainState::AcceptBlock(const std::shared_ptr& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) { diff --git a/src/validation.h b/src/validation.h index a18153ccff..6c80cb7518 100644 --- a/src/validation.h +++ b/src/validation.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -312,13 +313,6 @@ bool GetAddressUnspent(uint160 addressHash, int type, /** Initializes the script-execution cache */ void InitScriptExecutionCache(); - -/** Functions for disk access for blocks */ -bool ReadBlockFromDisk(CBlock& block, const FlatFilePos& pos, const Consensus::Params& consensusParams); -bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex, const Consensus::Params& consensusParams); - -bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex); - /** Functions for validating blocks and updating the block tree */ /** Context-independent validity checks */ @@ -921,6 +915,7 @@ private: friend CChain& ChainActive(); public: + std::thread m_load_block; //! A single BlockManager instance is shared across each constructed //! chainstate to avoid duplicating block metadata. BlockManager m_blockman GUARDED_BY(::cs_main); diff --git a/src/zmq/zmqpublishnotifier.cpp b/src/zmq/zmqpublishnotifier.cpp index 2724f8b17b..0f4444c535 100644 --- a/src/zmq/zmqpublishnotifier.cpp +++ b/src/zmq/zmqpublishnotifier.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh index 5839a54fa5..88b2d1d2c2 100755 --- a/test/lint/lint-circular-dependencies.sh +++ b/test/lint/lint-circular-dependencies.sh @@ -11,7 +11,9 @@ export LC_ALL=C EXPECTED_CIRCULAR_DEPENDENCIES=( "chainparamsbase -> util/system -> chainparamsbase" "index/txindex -> validation -> index/txindex" - "index/blockfilterindex -> validation -> index/blockfilterindex" + "node/blockstorage -> validation -> node/blockstorage" + "index/blockfilterindex -> node/blockstorage -> validation -> index/blockfilterindex" + "index/base -> validation -> index/blockfilterindex -> index/base" "policy/fees -> txmempool -> policy/fees" "qt/addresstablemodel -> qt/walletmodel -> qt/addresstablemodel" "qt/bitcoingui -> qt/walletframe -> qt/bitcoingui" @@ -23,6 +25,7 @@ EXPECTED_CIRCULAR_DEPENDENCIES=( "node/coinstats -> validation -> node/coinstats" # Dash "coinjoin/server -> net_processing -> coinjoin/server" + "dsnotificationinterface -> llmq/chainlocks -> node/blockstorage -> dsnotificationinterface" "evo/cbtx -> evo/simplifiedmns -> evo/cbtx" "evo/deterministicmns -> llmq/commitment -> evo/deterministicmns" "evo/deterministicmns -> llmq/utils -> evo/deterministicmns"