merge bitcoin#21575: Create blockstorage module

This commit is contained in:
Kittywhiskers Van Gogh 2023-07-24 18:42:13 +00:00 committed by PastaPastaPasta
parent 94b706e402
commit b1643e7c86
25 changed files with 316 additions and 229 deletions

View File

@ -247,6 +247,7 @@ BITCOIN_CORE_H = \
netbase.h \ netbase.h \
netfulfilledman.h \ netfulfilledman.h \
netmessagemaker.h \ netmessagemaker.h \
node/blockstorage.h \
node/coin.h \ node/coin.h \
node/coinstats.h \ node/coinstats.h \
node/context.h \ node/context.h \
@ -441,6 +442,7 @@ libbitcoin_server_a_SOURCES = \
net.cpp \ net.cpp \
netfulfilledman.cpp \ netfulfilledman.cpp \
net_processing.cpp \ net_processing.cpp \
node/blockstorage.cpp \
node/coin.cpp \ node/coin.cpp \
node/coinstats.cpp \ node/coinstats.cpp \
node/context.cpp \ node/context.cpp \

View File

@ -8,6 +8,7 @@
#include <llmq/chainlocks.h> #include <llmq/chainlocks.h>
#include <llmq/commitment.h> #include <llmq/commitment.h>
#include <llmq/utils.h> #include <llmq/utils.h>
#include <node/blockstorage.h>
#include <evo/simplifiedmns.h> #include <evo/simplifiedmns.h>
#include <evo/specialtx.h> #include <evo/specialtx.h>
#include <consensus/validation.h> #include <consensus/validation.h>

View File

@ -12,6 +12,7 @@
#include <chain.h> #include <chain.h>
#include <logging.h> #include <logging.h>
#include <validation.h> #include <validation.h>
#include <node/blockstorage.h>
#include <algorithm> #include <algorithm>
#include <exception> #include <exception>

View File

@ -11,6 +11,7 @@
#include <llmq/commitment.h> #include <llmq/commitment.h>
#include <llmq/quorums.h> #include <llmq/quorums.h>
#include <llmq/utils.h> #include <llmq/utils.h>
#include <node/blockstorage.h>
#include <evo/specialtx.h> #include <evo/specialtx.h>
#include <pubkey.h> #include <pubkey.h>

View File

@ -4,11 +4,12 @@
#include <chainparams.h> #include <chainparams.h>
#include <index/base.h> #include <index/base.h>
#include <node/blockstorage.h>
#include <shutdown.h> #include <shutdown.h>
#include <tinyformat.h> #include <tinyformat.h>
#include <ui_interface.h> #include <ui_interface.h>
#include <util/translation.h> #include <util/translation.h>
#include <validation.h> #include <validation.h> // For g_chainman
#include <warnings.h> #include <warnings.h>
constexpr char DB_BEST_BLOCK = 'B'; constexpr char DB_BEST_BLOCK = 'B';

View File

@ -6,9 +6,8 @@
#include <dbwrapper.h> #include <dbwrapper.h>
#include <index/blockfilterindex.h> #include <index/blockfilterindex.h>
#include <node/blockstorage.h>
#include <serialize.h> #include <serialize.h>
#include <util/system.h>
#include <validation.h>
/* The index database stores three items for each block: the disk location of the encoded filter, /* 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 * its dSHA256 hash, and the header. Those belonging to blocks on the active chain are indexed by

View File

@ -20,7 +20,6 @@
#include <context.h> #include <context.h>
#include <node/coinstats.h> #include <node/coinstats.h>
#include <compat/sanity.h> #include <compat/sanity.h>
#include <consensus/validation.h>
#include <fs.h> #include <fs.h>
#include <hash.h> #include <hash.h>
#include <httpserver.h> #include <httpserver.h>
@ -36,6 +35,7 @@
#include <net_permissions.h> #include <net_permissions.h>
#include <net_processing.h> #include <net_processing.h>
#include <netbase.h> #include <netbase.h>
#include <node/blockstorage.h>
#include <node/context.h> #include <node/context.h>
#include <policy/feerate.h> #include <policy/feerate.h>
#include <policy/fees.h> #include <policy/fees.h>
@ -123,7 +123,6 @@
static const bool DEFAULT_PROXYRANDOMIZE = true; static const bool DEFAULT_PROXYRANDOMIZE = true;
static const bool DEFAULT_REST_ENABLE = false; static const bool DEFAULT_REST_ENABLE = false;
static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
static CDSNotificationInterface* pdsNotificationInterface = nullptr; static CDSNotificationInterface* pdsNotificationInterface = nullptr;
@ -189,8 +188,6 @@ static fs::path GetPidFile(const ArgsManager& args)
static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle; static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle;
static std::thread g_load_block;
void Interrupt(NodeContext& node) void Interrupt(NodeContext& node)
{ {
InterruptHTTPServer(); InterruptHTTPServer();
@ -266,7 +263,7 @@ void PrepareShutdown(NodeContext& node)
// After everything has been shut down, but before things get flushed, stop the // After everything has been shut down, but before things get flushed, stop the
// CScheduler/checkqueue, threadGroup and load block thread. // CScheduler/checkqueue, threadGroup and load block thread.
if (node.scheduler) node.scheduler->stop(); 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(); StopScriptCheckWorkerThreads();
// After there are no more peers/RPC left to give us new data which may generate // 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 // 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 // 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 // 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<fs::path> 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) static void PeriodicStats(ArgsManager& args, const CTxMemPool& mempool)
{ {
assert(args.GetBoolArg("-statsenabled", DEFAULT_STATSD_ENABLE)); assert(args.GetBoolArg("-statsenabled", DEFAULT_STATSD_ENABLE));
@ -2468,7 +2354,9 @@ bool AppInitMain(const CoreContext& context, NodeContext& node, interfaces::Bloc
vImportFiles.push_back(strFile); vImportFiles.push_back(strFile);
} }
g_load_block = std::thread(&TraceThread<std::function<void()>>, "loadblk", [=, &chainman, &args]{ ThreadImport(chainman, vImportFiles, args); }); chainman.m_load_block = std::thread(&TraceThread<std::function<void()>>, "loadblk", [=, &chainman, &args] {
ThreadImport(chainman, *pdsNotificationInterface ,vImportFiles, args);
});
// Wait for genesis block to be processed // Wait for genesis block to be processed
{ {

View File

@ -15,6 +15,7 @@
#include <consensus/validation.h> #include <consensus/validation.h>
#include <net.h> #include <net.h>
#include <net_processing.h> #include <net_processing.h>
#include <node/blockstorage.h>
#include <primitives/block.h> #include <primitives/block.h>
#include <primitives/transaction.h> #include <primitives/transaction.h>
#include <saltedhasher.h> #include <saltedhasher.h>

View File

@ -13,6 +13,7 @@
#include <consensus/validation.h> #include <consensus/validation.h>
#include <masternode/sync.h> #include <masternode/sync.h>
#include <net_processing.h> #include <net_processing.h>
#include <node/blockstorage.h>
#include <scheduler.h> #include <scheduler.h>
#include <spork.h> #include <spork.h>
#include <txmempool.h> #include <txmempool.h>

View File

@ -17,6 +17,7 @@
#include <merkleblock.h> #include <merkleblock.h>
#include <netmessagemaker.h> #include <netmessagemaker.h>
#include <netbase.h> #include <netbase.h>
#include <node/blockstorage.h>
#include <policy/policy.h> #include <policy/policy.h>
#include <primitives/block.h> #include <primitives/block.h>
#include <primitives/transaction.h> #include <primitives/transaction.h>

View File

@ -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 calling code in the other directories directly, and only invoke it indirectly
through the more limited [`src/interfaces/`](../interfaces/) classes. through the more limited [`src/interfaces/`](../interfaces/) classes.
The [`src/node/`](./) directory is a new directory introduced in This directory is at the moment
[#14978](https://github.com/bitcoin/bitcoin/pull/14978) and at the moment is
sparsely populated. Eventually more substantial files like sparsely populated. Eventually more substantial files like
[`src/validation.cpp`](../validation.cpp) and [`src/validation.cpp`](../validation.cpp) and
[`src/txmempool.cpp`](../txmempool.cpp) might be moved there. [`src/txmempool.cpp`](../txmempool.cpp) might be moved there.

223
src/node/blockstorage.cpp Normal file
View File

@ -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 <node/blockstorage.h>
#include <chain.h>
#include <chainparams.h>
#include <consensus/validation.h>
#include <dsnotificationinterface.h>
#include <evo/deterministicmns.h>
#include <flatfile.h>
#include <fs.h>
#include <masternode/node.h>
#include <pow.h>
#include <shutdown.h>
#include <streams.h>
#include <util/system.h>
#include <validation.h>
#include <walletinitinterface.h>
// 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<fs::path> 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);
}

39
src/node/blockstorage.h Normal file
View File

@ -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 <cstdint>
#include <vector>
#include <fs.h>
#include <protocol.h> // 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<fs::path> vImportFiles, const ArgsManager& args);
#endif // BITCOIN_NODE_BLOCKSTORAGE_H

View File

@ -22,6 +22,7 @@
#include <net_processing.h> #include <net_processing.h>
#include <netaddress.h> #include <netaddress.h>
#include <netbase.h> #include <netbase.h>
#include <node/blockstorage.h>
#include <node/coin.h> #include <node/coin.h>
#include <node/context.h> #include <node/context.h>
#include <node/transaction.h> #include <node/transaction.h>

View File

@ -12,6 +12,7 @@
#include <llmq/chainlocks.h> #include <llmq/chainlocks.h>
#include <llmq/context.h> #include <llmq/context.h>
#include <llmq/instantsend.h> #include <llmq/instantsend.h>
#include <node/blockstorage.h>
#include <node/context.h> #include <node/context.h>
#include <primitives/block.h> #include <primitives/block.h>
#include <primitives/transaction.h> #include <primitives/transaction.h>

View File

@ -16,6 +16,7 @@
#include <index/blockfilterindex.h> #include <index/blockfilterindex.h>
#include <index/txindex.h> #include <index/txindex.h>
#include <llmq/context.h> #include <llmq/context.h>
#include <node/blockstorage.h>
#include <node/coinstats.h> #include <node/coinstats.h>
#include <node/context.h> #include <node/context.h>
#include <node/utxo_snapshot.h> #include <node/utxo_snapshot.h>

View File

@ -6,6 +6,7 @@
#include <evo/deterministicmns.h> #include <evo/deterministicmns.h>
#include <governance/classes.h> #include <governance/classes.h>
#include <index/txindex.h> #include <index/txindex.h>
#include <node/blockstorage.h>
#include <node/context.h> #include <node/context.h>
#include <governance/governance.h> #include <governance/governance.h>
#include <masternode/node.h> #include <masternode/node.h>

View File

@ -14,6 +14,7 @@
#include <init.h> #include <init.h>
#include <key_io.h> #include <key_io.h>
#include <merkleblock.h> #include <merkleblock.h>
#include <node/blockstorage.h>
#include <node/coin.h> #include <node/coin.h>
#include <node/context.h> #include <node/context.h>
#include <node/transaction.h> #include <node/transaction.h>

View File

@ -5,6 +5,10 @@
#include <shutdown.h> #include <shutdown.h>
#include <logging.h>
#include <ui_interface.h>
#include <warnings.h>
#include <config/bitcoin-config.h> #include <config/bitcoin-config.h>
#include <assert.h> #include <assert.h>
@ -17,6 +21,18 @@
#include <unistd.h> #include <unistd.h>
#endif #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<bool> fRequestShutdown(false); static std::atomic<bool> fRequestShutdown(false);
static std::atomic<bool> fRequestRestart(false); static std::atomic<bool> fRequestRestart(false);

View File

@ -6,6 +6,11 @@
#ifndef BITCOIN_SHUTDOWN_H #ifndef BITCOIN_SHUTDOWN_H
#define BITCOIN_SHUTDOWN_H #define BITCOIN_SHUTDOWN_H
#include <util/translation.h> // 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(), /** Initialize shutdown state. This must be called before using either StartShutdown(),
* AbortShutdown() or WaitForShutdown(). Calling ShutdownRequested() is always safe. * AbortShutdown() or WaitForShutdown(). Calling ShutdownRequested() is always safe.
*/ */

View File

@ -5,6 +5,7 @@
#include <test/util/blockfilter.h> #include <test/util/blockfilter.h>
#include <chainparams.h> #include <chainparams.h>
#include <node/blockstorage.h>
#include <validation.h> #include <validation.h>
bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex* block_index, BlockFilter& filter) bool ComputeFilter(BlockFilterType filter_type, const CBlockIndex* block_index, BlockFilter& filter)

View File

@ -22,6 +22,7 @@
#include <index/txindex.h> #include <index/txindex.h>
#include <logging.h> #include <logging.h>
#include <logging/timer.h> #include <logging/timer.h>
#include <node/blockstorage.h>
#include <node/coinstats.h> #include <node/coinstats.h>
#include <policy/policy.h> #include <policy/policy.h>
#include <policy/settings.h> #include <policy/settings.h>
@ -1087,72 +1088,6 @@ CTransactionRef GetTransaction(const CBlockIndex* const block_index, const CTxMe
return nullptr; 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) double ConvertBitsToDouble(unsigned int nBits)
{ {
int nShift = (nBits >> 24) & 0xff; int nShift = (nBits >> 24) & 0xff;
@ -1676,19 +1611,6 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex)
return true; 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()) static bool AbortNode(BlockValidationState& state, const std::string& strMessage, const bilingual_str& userMessage = bilingual_str())
{ {
AbortNode(strMessage, userMessage); 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); LOCK(cs_LastBlockFile);
@ -4224,25 +4147,6 @@ bool ChainstateManager::ProcessNewBlockHeaders(const std::vector<CBlockHeader>&
return true; 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 */ /** 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<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock)
{ {

View File

@ -34,6 +34,7 @@
#include <set> #include <set>
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include <thread>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -312,13 +313,6 @@ bool GetAddressUnspent(uint160 addressHash, int type,
/** Initializes the script-execution cache */ /** Initializes the script-execution cache */
void InitScriptExecutionCache(); 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 */ /** Functions for validating blocks and updating the block tree */
/** Context-independent validity checks */ /** Context-independent validity checks */
@ -921,6 +915,7 @@ private:
friend CChain& ChainActive(); friend CChain& ChainActive();
public: public:
std::thread m_load_block;
//! A single BlockManager instance is shared across each constructed //! A single BlockManager instance is shared across each constructed
//! chainstate to avoid duplicating block metadata. //! chainstate to avoid duplicating block metadata.
BlockManager m_blockman GUARDED_BY(::cs_main); BlockManager m_blockman GUARDED_BY(::cs_main);

View File

@ -6,6 +6,7 @@
#include <chain.h> #include <chain.h>
#include <chainparams.h> #include <chainparams.h>
#include <node/blockstorage.h>
#include <streams.h> #include <streams.h>
#include <validation.h> #include <validation.h>
#include <zmq/zmqutil.h> #include <zmq/zmqutil.h>

View File

@ -11,7 +11,9 @@ export LC_ALL=C
EXPECTED_CIRCULAR_DEPENDENCIES=( EXPECTED_CIRCULAR_DEPENDENCIES=(
"chainparamsbase -> util/system -> chainparamsbase" "chainparamsbase -> util/system -> chainparamsbase"
"index/txindex -> validation -> index/txindex" "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" "policy/fees -> txmempool -> policy/fees"
"qt/addresstablemodel -> qt/walletmodel -> qt/addresstablemodel" "qt/addresstablemodel -> qt/walletmodel -> qt/addresstablemodel"
"qt/bitcoingui -> qt/walletframe -> qt/bitcoingui" "qt/bitcoingui -> qt/walletframe -> qt/bitcoingui"
@ -23,6 +25,7 @@ EXPECTED_CIRCULAR_DEPENDENCIES=(
"node/coinstats -> validation -> node/coinstats" "node/coinstats -> validation -> node/coinstats"
# Dash # Dash
"coinjoin/server -> net_processing -> coinjoin/server" "coinjoin/server -> net_processing -> coinjoin/server"
"dsnotificationinterface -> llmq/chainlocks -> node/blockstorage -> dsnotificationinterface"
"evo/cbtx -> evo/simplifiedmns -> evo/cbtx" "evo/cbtx -> evo/simplifiedmns -> evo/cbtx"
"evo/deterministicmns -> llmq/commitment -> evo/deterministicmns" "evo/deterministicmns -> llmq/commitment -> evo/deterministicmns"
"evo/deterministicmns -> llmq/utils -> evo/deterministicmns" "evo/deterministicmns -> llmq/utils -> evo/deterministicmns"