Changeset View
Changeset View
Standalone View
Standalone View
src/init.cpp
Show All 12 Lines | |||||
#include <amount.h> | #include <amount.h> | ||||
#include <avalanche/processor.h> | #include <avalanche/processor.h> | ||||
#include <banman.h> | #include <banman.h> | ||||
#include <blockdb.h> | #include <blockdb.h> | ||||
#include <blockfilter.h> | #include <blockfilter.h> | ||||
#include <chain.h> | #include <chain.h> | ||||
#include <chainparams.h> | #include <chainparams.h> | ||||
#include <checkpoints.h> | #include <checkpoints.h> | ||||
#include <coins.h> | |||||
#include <compat/sanity.h> | #include <compat/sanity.h> | ||||
#include <config.h> | #include <config.h> | ||||
#include <consensus/validation.h> | #include <consensus/validation.h> | ||||
#include <flatfile.h> | #include <flatfile.h> | ||||
#include <fs.h> | #include <fs.h> | ||||
#include <httprpc.h> | #include <httprpc.h> | ||||
#include <httpserver.h> | #include <httpserver.h> | ||||
#include <index/blockfilterindex.h> | #include <index/blockfilterindex.h> | ||||
▲ Show 20 Lines • Show All 108 Lines • ▼ Show 20 Lines | |||||
// Shutdown() is then called to clean up database connections, and stop other | // Shutdown() is then called to clean up database connections, and stop other | ||||
// threads that should only be stopped after the main network-processing threads | // threads that should only be stopped after the main network-processing threads | ||||
// have exited. | // have exited. | ||||
// | // | ||||
// Shutdown for Qt is very similar, only it uses a QTimer to detect | // Shutdown for Qt is very similar, only it uses a QTimer to detect | ||||
// ShutdownRequested() getting set, and then does the normal Qt shutdown thing. | // ShutdownRequested() getting set, and then does the normal Qt shutdown thing. | ||||
// | // | ||||
static std::unique_ptr<CCoinsViewErrorCatcher> pcoinscatcher; | |||||
static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle; | static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle; | ||||
static boost::thread_group threadGroup; | static boost::thread_group threadGroup; | ||||
void Interrupt(NodeContext &node) { | void Interrupt(NodeContext &node) { | ||||
InterruptHTTPServer(); | InterruptHTTPServer(); | ||||
InterruptHTTPRPC(); | InterruptHTTPRPC(); | ||||
InterruptRPC(); | InterruptRPC(); | ||||
▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | void Shutdown(NodeContext &node) { | ||||
if (::g_mempool.IsLoaded() && | if (::g_mempool.IsLoaded() && | ||||
gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) { | gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) { | ||||
DumpMempool(::g_mempool); | DumpMempool(::g_mempool); | ||||
} | } | ||||
// FlushStateToDisk generates a ChainStateFlushed callback, which we should | // FlushStateToDisk generates a ChainStateFlushed callback, which we should | ||||
// avoid missing | // avoid missing | ||||
if (pcoinsTip != nullptr) { | // g_chainstate is referenced here directly (instead of | ||||
::ChainstateActive().ForceFlushStateToDisk(); | // ::ChainstateActive()) because it may not have been initialized yet. | ||||
if (g_chainstate && g_chainstate->CanFlushToDisk()) { | |||||
g_chainstate->ForceFlushStateToDisk(); | |||||
} | } | ||||
// After there are no more peers/RPC left to give us new data which may | // After there are no more peers/RPC left to give us new data which may | ||||
// generate CValidationInterface callbacks, flush them... | // generate CValidationInterface callbacks, flush them... | ||||
GetMainSignals().FlushBackgroundCallbacks(); | GetMainSignals().FlushBackgroundCallbacks(); | ||||
// Any future callbacks will be dropped. This should absolutely be safe - if | // Any future callbacks will be dropped. This should absolutely be safe - if | ||||
// missing a callback results in an unrecoverable situation, unclean | // missing a callback results in an unrecoverable situation, unclean | ||||
// shutdown would too. The only reason to do the above flushes is to let the | // shutdown would too. The only reason to do the above flushes is to let the | ||||
// wallet catch up with our current chain to avoid any strange pruning edge | // wallet catch up with our current chain to avoid any strange pruning edge | ||||
// cases and make next startup faster by avoiding rescan. | // cases and make next startup faster by avoiding rescan. | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
if (pcoinsTip != nullptr) { | if (g_chainstate && g_chainstate->CanFlushToDisk()) { | ||||
::ChainstateActive().ForceFlushStateToDisk(); | g_chainstate->ForceFlushStateToDisk(); | ||||
g_chainstate->ResetCoinsViews(); | |||||
} | } | ||||
pcoinsTip.reset(); | |||||
pcoinscatcher.reset(); | |||||
pcoinsdbview.reset(); | |||||
pblocktree.reset(); | pblocktree.reset(); | ||||
} | } | ||||
for (const auto &client : node.chain_clients) { | for (const auto &client : node.chain_clients) { | ||||
client->stop(); | client->stop(); | ||||
} | } | ||||
#if ENABLE_ZMQ | #if ENABLE_ZMQ | ||||
if (g_zmq_notification_interface) { | if (g_zmq_notification_interface) { | ||||
▲ Show 20 Lines • Show All 2,109 Lines • ▼ Show 20 Lines | while (!fLoaded && !ShutdownRequested()) { | ||||
const bool fReset = fReindex; | const bool fReset = fReindex; | ||||
std::string strLoadError; | std::string strLoadError; | ||||
uiInterface.InitMessage(_("Loading block index...").translated); | uiInterface.InitMessage(_("Loading block index...").translated); | ||||
do { | do { | ||||
const int64_t load_block_index_start_time = GetTimeMillis(); | const int64_t load_block_index_start_time = GetTimeMillis(); | ||||
try { | try { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
// This statement makes ::ChainstateActive() usable. | |||||
g_chainstate = std::make_unique<CChainState>(); | |||||
UnloadBlockIndex(); | UnloadBlockIndex(); | ||||
pcoinsTip.reset(); | |||||
pcoinsdbview.reset(); | |||||
pcoinscatcher.reset(); | |||||
// new CBlockTreeDB tries to delete the existing file, which | // new CBlockTreeDB tries to delete the existing file, which | ||||
// fails if it's still open from the previous loop. Close it | // fails if it's still open from the previous loop. Close it | ||||
// first: | // first: | ||||
pblocktree.reset(); | pblocktree.reset(); | ||||
pblocktree.reset( | pblocktree.reset( | ||||
new CBlockTreeDB(nBlockTreeDBCache, false, fReset)); | new CBlockTreeDB(nBlockTreeDBCache, false, fReset)); | ||||
if (fReset) { | if (fReset) { | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | while (!fLoaded && !ShutdownRequested()) { | ||||
strLoadError = | strLoadError = | ||||
_("Error initializing block database").translated; | _("Error initializing block database").translated; | ||||
break; | break; | ||||
} | } | ||||
// At this point we're either in reindex or we've loaded a | // At this point we're either in reindex or we've loaded a | ||||
// useful block tree into BlockIndex()! | // useful block tree into BlockIndex()! | ||||
pcoinsdbview.reset(new CCoinsViewDB( | ::ChainstateActive().InitCoinsDB( | ||||
nCoinDBCache, false, fReset || fReindexChainState)); | /* cache_size_bytes */ nCoinDBCache, | ||||
pcoinscatcher.reset( | /* in_memory */ false, | ||||
new CCoinsViewErrorCatcher(pcoinsdbview.get())); | /* should_wipe */ fReset || fReindexChainState); | ||||
pcoinscatcher->AddReadErrCallback([]() { | |||||
::ChainstateActive().CoinsErrorCatcher().AddReadErrCallback( | |||||
[]() { | |||||
uiInterface.ThreadSafeMessageBox( | uiInterface.ThreadSafeMessageBox( | ||||
_("Error reading from database, shutting down.") | _("Error reading from database, shutting down.") | ||||
.translated, | .translated, | ||||
"", CClientUIInterface::MSG_ERROR); | "", CClientUIInterface::MSG_ERROR); | ||||
}); | }); | ||||
// If necessary, upgrade from older database format. | // If necessary, upgrade from older database format. | ||||
// This is a no-op if we cleared the coinsviewdb with -reindex | // This is a no-op if we cleared the coinsviewdb with -reindex | ||||
// or -reindex-chainstate | // or -reindex-chainstate | ||||
if (!pcoinsdbview->Upgrade()) { | if (!::ChainstateActive().CoinsDB().Upgrade()) { | ||||
strLoadError = | strLoadError = | ||||
_("Error upgrading chainstate database").translated; | _("Error upgrading chainstate database").translated; | ||||
break; | break; | ||||
} | } | ||||
// ReplayBlocks is a no-op if we cleared the coinsviewdb with | // ReplayBlocks is a no-op if we cleared the coinsviewdb with | ||||
// -reindex or -reindex-chainstate | // -reindex or -reindex-chainstate | ||||
if (!ReplayBlocks(params, pcoinsdbview.get())) { | if (!ReplayBlocks(params, &::ChainstateActive().CoinsDB())) { | ||||
strLoadError = | strLoadError = | ||||
_("Unable to replay blocks. You will need to rebuild " | _("Unable to replay blocks. You will need to rebuild " | ||||
"the database using -reindex-chainstate.") | "the database using -reindex-chainstate.") | ||||
.translated; | .translated; | ||||
break; | break; | ||||
} | } | ||||
// The on-disk coinsdb is now in a good state, create the cache | // The on-disk coinsdb is now in a good state, create the cache | ||||
pcoinsTip.reset(new CCoinsViewCache(pcoinscatcher.get())); | ::ChainstateActive().InitCoinsCache(); | ||||
assert(::ChainstateActive().CanFlushToDisk()); | |||||
bool is_coinsview_empty = fReset || fReindexChainState || | bool is_coinsview_empty = | ||||
pcoinsTip->GetBestBlock().IsNull(); | fReset || fReindexChainState || | ||||
::ChainstateActive().CoinsTip().GetBestBlock().IsNull(); | |||||
if (!is_coinsview_empty) { | if (!is_coinsview_empty) { | ||||
// LoadChainTip sets ::ChainActive() based on pcoinsTip's | // LoadChainTip sets ::ChainActive() based on CoinsTip()'s | ||||
// best block | // best block | ||||
if (!LoadChainTip(config)) { | if (!LoadChainTip(config)) { | ||||
strLoadError = | strLoadError = | ||||
_("Error initializing block database").translated; | _("Error initializing block database").translated; | ||||
break; | break; | ||||
} | } | ||||
assert(::ChainActive().Tip() != nullptr); | assert(::ChainActive().Tip() != nullptr); | ||||
Show All 19 Lines | while (!fLoaded && !ShutdownRequested()) { | ||||
"incorrectly. Only rebuild the block database if " | "incorrectly. Only rebuild the block database if " | ||||
"you are sure that your computer's date and time " | "you are sure that your computer's date and time " | ||||
"are correct") | "are correct") | ||||
.translated; | .translated; | ||||
break; | break; | ||||
} | } | ||||
if (!CVerifyDB().VerifyDB( | if (!CVerifyDB().VerifyDB( | ||||
config, pcoinsdbview.get(), | config, &::ChainstateActive().CoinsDB(), | ||||
gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL), | gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL), | ||||
gArgs.GetArg("-checkblocks", | gArgs.GetArg("-checkblocks", | ||||
DEFAULT_CHECKBLOCKS))) { | DEFAULT_CHECKBLOCKS))) { | ||||
strLoadError = | strLoadError = | ||||
_("Corrupted block database detected").translated; | _("Corrupted block database detected").translated; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 249 Lines • Show Last 20 Lines |