Changeset View
Changeset View
Standalone View
Standalone View
src/init.cpp
Show All 11 Lines | |||||
#include "addrman.h" | #include "addrman.h" | ||||
#include "amount.h" | #include "amount.h" | ||||
#include "chain.h" | #include "chain.h" | ||||
#include "chainparams.h" | #include "chainparams.h" | ||||
#include "checkpoints.h" | #include "checkpoints.h" | ||||
#include "compat/sanity.h" | #include "compat/sanity.h" | ||||
#include "config.h" | #include "config.h" | ||||
#include "consensus/validation.h" | #include "consensus/validation.h" | ||||
#include "fs.h" | |||||
#include "httprpc.h" | #include "httprpc.h" | ||||
#include "httpserver.h" | #include "httpserver.h" | ||||
#include "key.h" | #include "key.h" | ||||
#include "miner.h" | #include "miner.h" | ||||
#include "net.h" | #include "net.h" | ||||
#include "net_processing.h" | #include "net_processing.h" | ||||
#include "netbase.h" | #include "netbase.h" | ||||
#include "policy/policy.h" | #include "policy/policy.h" | ||||
Show All 26 Lines | |||||
#include <signal.h> | #include <signal.h> | ||||
#endif | #endif | ||||
#include <boost/algorithm/string/classification.hpp> | #include <boost/algorithm/string/classification.hpp> | ||||
#include <boost/algorithm/string/predicate.hpp> | #include <boost/algorithm/string/predicate.hpp> | ||||
#include <boost/algorithm/string/replace.hpp> | #include <boost/algorithm/string/replace.hpp> | ||||
#include <boost/algorithm/string/split.hpp> | #include <boost/algorithm/string/split.hpp> | ||||
#include <boost/bind.hpp> | #include <boost/bind.hpp> | ||||
#include <boost/filesystem.hpp> | |||||
#include <boost/interprocess/sync/file_lock.hpp> | #include <boost/interprocess/sync/file_lock.hpp> | ||||
#include <boost/thread.hpp> | #include <boost/thread.hpp> | ||||
#if ENABLE_ZMQ | #if ENABLE_ZMQ | ||||
#include "zmq/zmqnotificationinterface.h" | #include "zmq/zmqnotificationinterface.h" | ||||
#endif | #endif | ||||
bool fFeeEstimatesInitialized = false; | bool fFeeEstimatesInitialized = false; | ||||
▲ Show 20 Lines • Show All 130 Lines • ▼ Show 20 Lines | #endif | ||||
peerLogic.reset(); | peerLogic.reset(); | ||||
g_connman.reset(); | g_connman.reset(); | ||||
StopTorControl(); | StopTorControl(); | ||||
UnregisterNodeSignals(GetNodeSignals()); | UnregisterNodeSignals(GetNodeSignals()); | ||||
if (fDumpMempoolLater) DumpMempool(); | if (fDumpMempoolLater) DumpMempool(); | ||||
if (fFeeEstimatesInitialized) { | if (fFeeEstimatesInitialized) { | ||||
boost::filesystem::path est_path = | fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; | ||||
GetDataDir() / FEE_ESTIMATES_FILENAME; | CAutoFile est_fileout(fsbridge::fopen(est_path, "wb"), SER_DISK, | ||||
CAutoFile est_fileout(fopen(est_path.string().c_str(), "wb"), SER_DISK, | |||||
CLIENT_VERSION); | CLIENT_VERSION); | ||||
if (!est_fileout.IsNull()) | if (!est_fileout.IsNull()) | ||||
mempool.WriteFeeEstimates(est_fileout); | mempool.WriteFeeEstimates(est_fileout); | ||||
else | else | ||||
LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, | LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, | ||||
est_path.string()); | est_path.string()); | ||||
fFeeEstimatesInitialized = false; | fFeeEstimatesInitialized = false; | ||||
} | } | ||||
Show All 21 Lines | if (pzmqNotificationInterface) { | ||||
UnregisterValidationInterface(pzmqNotificationInterface); | UnregisterValidationInterface(pzmqNotificationInterface); | ||||
delete pzmqNotificationInterface; | delete pzmqNotificationInterface; | ||||
pzmqNotificationInterface = nullptr; | pzmqNotificationInterface = nullptr; | ||||
} | } | ||||
#endif | #endif | ||||
#ifndef WIN32 | #ifndef WIN32 | ||||
try { | try { | ||||
boost::filesystem::remove(GetPidFile()); | fs::remove(GetPidFile()); | ||||
} catch (const boost::filesystem::filesystem_error &e) { | } catch (const fs::filesystem_error &e) { | ||||
LogPrintf("%s: Unable to remove pidfile: %s\n", __func__, e.what()); | LogPrintf("%s: Unable to remove pidfile: %s\n", __func__, e.what()); | ||||
} | } | ||||
#endif | #endif | ||||
UnregisterAllValidationInterfaces(); | UnregisterAllValidationInterfaces(); | ||||
#ifdef ENABLE_WALLET | #ifdef ENABLE_WALLET | ||||
delete pwalletMain; | delete pwalletMain; | ||||
pwalletMain = nullptr; | pwalletMain = nullptr; | ||||
#endif | #endif | ||||
▲ Show 20 Lines • Show All 671 Lines • ▼ Show 20 Lines | |||||
// If we're using -prune with -reindex, then delete block files that will be | // 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 | // 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 | // and looping until a blockfile is missing, do the same here to delete any | ||||
// later block files after a gap. Also delete all rev files since they'll be | // later block files after a gap. Also delete all rev files since they'll be | ||||
// rewritten by the reindex anyway. This ensures that vinfoBlockFile is in sync | // rewritten by the reindex anyway. This ensures that vinfoBlockFile is in sync | ||||
// with what's actually on disk by the time we start downloading, so that | // with what's actually on disk by the time we start downloading, so that | ||||
// pruning works correctly. | // pruning works correctly. | ||||
void CleanupBlockRevFiles() { | void CleanupBlockRevFiles() { | ||||
std::map<std::string, boost::filesystem::path> mapBlockFiles; | std::map<std::string, fs::path> mapBlockFiles; | ||||
// Glob all blk?????.dat and rev?????.dat files from the blocks directory. | // Glob all blk?????.dat and rev?????.dat files from the blocks directory. | ||||
// Remove the rev files immediately and insert the blk file paths into an | // Remove the rev files immediately and insert the blk file paths into an | ||||
// ordered map keyed by block file index. | // ordered map keyed by block file index. | ||||
LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for " | LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for " | ||||
"-reindex with -prune\n"); | "-reindex with -prune\n"); | ||||
boost::filesystem::path blocksdir = GetDataDir() / "blocks"; | fs::path blocksdir = GetDataDir() / "blocks"; | ||||
for (boost::filesystem::directory_iterator it(blocksdir); | for (fs::directory_iterator it(blocksdir); it != fs::directory_iterator(); | ||||
it != boost::filesystem::directory_iterator(); it++) { | it++) { | ||||
if (is_regular_file(*it) && | if (is_regular_file(*it) && | ||||
it->path().filename().string().length() == 12 && | it->path().filename().string().length() == 12 && | ||||
it->path().filename().string().substr(8, 4) == ".dat") { | it->path().filename().string().substr(8, 4) == ".dat") { | ||||
if (it->path().filename().string().substr(0, 3) == "blk") | if (it->path().filename().string().substr(0, 3) == "blk") | ||||
mapBlockFiles[it->path().filename().string().substr(3, 5)] = | mapBlockFiles[it->path().filename().string().substr(3, 5)] = | ||||
it->path(); | it->path(); | ||||
else if (it->path().filename().string().substr(0, 3) == "rev") | else if (it->path().filename().string().substr(0, 3) == "rev") | ||||
remove(it->path()); | remove(it->path()); | ||||
} | } | ||||
} | } | ||||
// Remove all block files that aren't part of a contiguous set starting at | // Remove all block files that aren't part of a contiguous set starting at | ||||
// zero by walking the ordered map (keys are block file indices) by keeping | // zero by walking the ordered map (keys are block file indices) by keeping | ||||
// a separate counter. Once we hit a gap (or if 0 doesn't exist) start | // a separate counter. Once we hit a gap (or if 0 doesn't exist) start | ||||
// removing block files. | // removing block files. | ||||
int nContigCounter = 0; | int nContigCounter = 0; | ||||
for (const std::pair<std::string, boost::filesystem::path> &item : | for (const std::pair<std::string, fs::path> &item : mapBlockFiles) { | ||||
mapBlockFiles) { | |||||
if (atoi(item.first) == nContigCounter) { | if (atoi(item.first) == nContigCounter) { | ||||
nContigCounter++; | nContigCounter++; | ||||
continue; | continue; | ||||
} | } | ||||
remove(item.second); | remove(item.second); | ||||
} | } | ||||
} | } | ||||
void ThreadImport(const Config &config, | void ThreadImport(const Config &config, std::vector<fs::path> vImportFiles) { | ||||
std::vector<boost::filesystem::path> vImportFiles) { | |||||
RenameThread("bitcoin-loadblk"); | RenameThread("bitcoin-loadblk"); | ||||
{ | { | ||||
CImportingNow imp; | CImportingNow imp; | ||||
// -reindex | // -reindex | ||||
if (fReindex) { | if (fReindex) { | ||||
int nFile = 0; | int nFile = 0; | ||||
while (true) { | while (true) { | ||||
CDiskBlockPos pos(nFile, 0); | CDiskBlockPos pos(nFile, 0); | ||||
if (!boost::filesystem::exists(GetBlockPosFilename(pos, "blk"))) | if (!fs::exists(GetBlockPosFilename(pos, "blk"))) | ||||
break; // No block files left to reindex | break; // No block files left to reindex | ||||
FILE *file = OpenBlockFile(pos, true); | FILE *file = OpenBlockFile(pos, true); | ||||
if (!file) break; // This error is logged in OpenBlockFile | if (!file) break; // This error is logged in OpenBlockFile | ||||
LogPrintf("Reindexing block file blk%05u.dat...\n", | LogPrintf("Reindexing block file blk%05u.dat...\n", | ||||
(unsigned int)nFile); | (unsigned int)nFile); | ||||
LoadExternalBlockFile(config, file, &pos); | LoadExternalBlockFile(config, file, &pos); | ||||
nFile++; | nFile++; | ||||
} | } | ||||
pblocktree->WriteReindexing(false); | pblocktree->WriteReindexing(false); | ||||
fReindex = false; | fReindex = false; | ||||
LogPrintf("Reindexing finished\n"); | LogPrintf("Reindexing finished\n"); | ||||
// To avoid ending up in a situation without genesis block, re-try | // To avoid ending up in a situation without genesis block, re-try | ||||
// initializing (no-op if reindexing worked): | // initializing (no-op if reindexing worked): | ||||
InitBlockIndex(config); | InitBlockIndex(config); | ||||
} | } | ||||
// hardcoded $DATADIR/bootstrap.dat | // hardcoded $DATADIR/bootstrap.dat | ||||
boost::filesystem::path pathBootstrap = GetDataDir() / "bootstrap.dat"; | fs::path pathBootstrap = GetDataDir() / "bootstrap.dat"; | ||||
if (boost::filesystem::exists(pathBootstrap)) { | if (fs::exists(pathBootstrap)) { | ||||
FILE *file = fopen(pathBootstrap.string().c_str(), "rb"); | FILE *file = fsbridge::fopen(pathBootstrap, "rb"); | ||||
if (file) { | if (file) { | ||||
boost::filesystem::path pathBootstrapOld = | fs::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; | ||||
GetDataDir() / "bootstrap.dat.old"; | |||||
LogPrintf("Importing bootstrap.dat...\n"); | LogPrintf("Importing bootstrap.dat...\n"); | ||||
LoadExternalBlockFile(config, file); | LoadExternalBlockFile(config, file); | ||||
RenameOver(pathBootstrap, pathBootstrapOld); | RenameOver(pathBootstrap, pathBootstrapOld); | ||||
} else { | } else { | ||||
LogPrintf("Warning: Could not open bootstrap file %s\n", | LogPrintf("Warning: Could not open bootstrap file %s\n", | ||||
pathBootstrap.string()); | pathBootstrap.string()); | ||||
} | } | ||||
} | } | ||||
// -loadblock= | // -loadblock= | ||||
for (const boost::filesystem::path &path : vImportFiles) { | for (const fs::path &path : vImportFiles) { | ||||
FILE *file = fopen(path.string().c_str(), "rb"); | FILE *file = fsbridge::fopen(path, "rb"); | ||||
if (file) { | if (file) { | ||||
LogPrintf("Importing blocks file %s...\n", path.string()); | LogPrintf("Importing blocks file %s...\n", path.string()); | ||||
LoadExternalBlockFile(config, file); | LoadExternalBlockFile(config, file); | ||||
} else { | } else { | ||||
LogPrintf("Warning: Could not open blocks file %s\n", | LogPrintf("Warning: Could not open blocks file %s\n", | ||||
path.string()); | path.string()); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 549 Lines • ▼ Show 20 Lines | #endif | ||||
return true; | return true; | ||||
} | } | ||||
static bool LockDataDirectory(bool probeOnly) { | static bool LockDataDirectory(bool probeOnly) { | ||||
std::string strDataDir = GetDataDir().string(); | std::string strDataDir = GetDataDir().string(); | ||||
// Make sure only a single Bitcoin process is using the data directory. | // Make sure only a single Bitcoin process is using the data directory. | ||||
boost::filesystem::path pathLockFile = GetDataDir() / ".lock"; | fs::path pathLockFile = GetDataDir() / ".lock"; | ||||
// empty lock file; created if it doesn't exist. | // empty lock file; created if it doesn't exist. | ||||
FILE *file = fopen(pathLockFile.string().c_str(), "a"); | FILE *file = fsbridge::fopen(pathLockFile, "a"); | ||||
if (file) fclose(file); | if (file) fclose(file); | ||||
try { | try { | ||||
static boost::interprocess::file_lock lock( | static boost::interprocess::file_lock lock( | ||||
pathLockFile.string().c_str()); | pathLockFile.string().c_str()); | ||||
if (!lock.try_lock()) { | if (!lock.try_lock()) { | ||||
return InitError( | return InitError( | ||||
strprintf(_("Cannot obtain a lock on data directory %s. %s is " | strprintf(_("Cannot obtain a lock on data directory %s. %s is " | ||||
▲ Show 20 Lines • Show All 277 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
// Step 7: load block chain | // Step 7: load block chain | ||||
fReindex = GetBoolArg("-reindex", false); | fReindex = GetBoolArg("-reindex", false); | ||||
bool fReindexChainState = GetBoolArg("-reindex-chainstate", false); | bool fReindexChainState = GetBoolArg("-reindex-chainstate", false); | ||||
// Upgrading to 0.8; hard-link the old blknnnn.dat files into /blocks/ | // Upgrading to 0.8; hard-link the old blknnnn.dat files into /blocks/ | ||||
boost::filesystem::path blocksDir = GetDataDir() / "blocks"; | fs::path blocksDir = GetDataDir() / "blocks"; | ||||
if (!boost::filesystem::exists(blocksDir)) { | if (!fs::exists(blocksDir)) { | ||||
boost::filesystem::create_directories(blocksDir); | fs::create_directories(blocksDir); | ||||
bool linked = false; | bool linked = false; | ||||
for (unsigned int i = 1; i < 10000; i++) { | for (unsigned int i = 1; i < 10000; i++) { | ||||
boost::filesystem::path source = | fs::path source = GetDataDir() / strprintf("blk%04u.dat", i); | ||||
GetDataDir() / strprintf("blk%04u.dat", i); | |||||
if (!boost::filesystem::exists(source)) { | if (!fs::exists(source)) { | ||||
break; | break; | ||||
} | } | ||||
boost::filesystem::path dest = | fs::path dest = blocksDir / strprintf("blk%05u.dat", i - 1); | ||||
blocksDir / strprintf("blk%05u.dat", i - 1); | |||||
try { | try { | ||||
boost::filesystem::create_hard_link(source, dest); | fs::create_hard_link(source, dest); | ||||
LogPrintf("Hardlinked %s -> %s\n", source.string(), | LogPrintf("Hardlinked %s -> %s\n", source.string(), | ||||
dest.string()); | dest.string()); | ||||
linked = true; | linked = true; | ||||
} catch (const boost::filesystem::filesystem_error &e) { | } catch (const fs::filesystem_error &e) { | ||||
// Note: hardlink creation failing is not a disaster, it just | // Note: hardlink creation failing is not a disaster, it just | ||||
// means blocks will get re-downloaded from peers. | // means blocks will get re-downloaded from peers. | ||||
LogPrintf("Error hardlinking blk%04u.dat: %s\n", i, e.what()); | LogPrintf("Error hardlinking blk%04u.dat: %s\n", i, e.what()); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (linked) { | if (linked) { | ||||
fReindex = true; | fReindex = true; | ||||
▲ Show 20 Lines • Show All 189 Lines • ▼ Show 20 Lines | #endif | ||||
// As the program has not fully started yet, Shutdown() is possibly | // As the program has not fully started yet, Shutdown() is possibly | ||||
// overkill. | // overkill. | ||||
if (fRequestShutdown) { | if (fRequestShutdown) { | ||||
LogPrintf("Shutdown requested. Exiting.\n"); | LogPrintf("Shutdown requested. Exiting.\n"); | ||||
return false; | return false; | ||||
} | } | ||||
LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart); | LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart); | ||||
boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; | fs::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME; | ||||
CAutoFile est_filein(fopen(est_path.string().c_str(), "rb"), SER_DISK, | CAutoFile est_filein(fsbridge::fopen(est_path, "rb"), SER_DISK, | ||||
CLIENT_VERSION); | CLIENT_VERSION); | ||||
// Allowed to fail as this file IS missing on first startup. | // Allowed to fail as this file IS missing on first startup. | ||||
if (!est_filein.IsNull()) mempool.ReadFeeEstimates(est_filein); | if (!est_filein.IsNull()) mempool.ReadFeeEstimates(est_filein); | ||||
fFeeEstimatesInitialized = true; | fFeeEstimatesInitialized = true; | ||||
// Encoded addresses using cashaddr instead of base58 | // Encoded addresses using cashaddr instead of base58 | ||||
// Activates by default on Jan, 14 | // Activates by default on Jan, 14 | ||||
config.SetCashAddrEncoding( | config.SetCashAddrEncoding( | ||||
Show All 32 Lines | if (chainActive.Tip() == nullptr) { | ||||
uiInterface.NotifyBlockTip.connect(BlockNotifyGenesisWait); | uiInterface.NotifyBlockTip.connect(BlockNotifyGenesisWait); | ||||
} else { | } else { | ||||
fHaveGenesis = true; | fHaveGenesis = true; | ||||
} | } | ||||
if (IsArgSet("-blocknotify")) | if (IsArgSet("-blocknotify")) | ||||
uiInterface.NotifyBlockTip.connect(BlockNotifyCallback); | uiInterface.NotifyBlockTip.connect(BlockNotifyCallback); | ||||
std::vector<boost::filesystem::path> vImportFiles; | std::vector<fs::path> vImportFiles; | ||||
if (mapMultiArgs.count("-loadblock")) { | if (mapMultiArgs.count("-loadblock")) { | ||||
for (const std::string &strFile : mapMultiArgs.at("-loadblock")) { | for (const std::string &strFile : mapMultiArgs.at("-loadblock")) { | ||||
vImportFiles.push_back(strFile); | vImportFiles.push_back(strFile); | ||||
} | } | ||||
} | } | ||||
threadGroup.create_thread( | threadGroup.create_thread( | ||||
boost::bind(&ThreadImport, std::ref(config), vImportFiles)); | boost::bind(&ThreadImport, std::ref(config), vImportFiles)); | ||||
▲ Show 20 Lines • Show All 60 Lines • Show Last 20 Lines |