Browse Source

Reorder AppInit2

This reorders AppInit2 into 10 sections:
1)  basic setup (OS stuff, signal handlers)
2)  parameter interactions (softset)
3)  interpreting options without side effects (just setting internal variables)
4)  application initialization (datadir lock, daemonize, pidfile, log file)
5)  network initialization (network params, proxy, binding)
6)  load blockchain
7)  load wallet
8)  import blocks (-loadblock=)
9)  load peers
10) start node/rpc threads
11) finished

This means invalid configurations will be detected as soon as possible
(in particular, before loading the block chain).
miguelfreitas
Pieter Wuille 13 years ago
parent
commit
7d80d2e3d7
  1. 398
      src/init.cpp

398
src/init.cpp

@ -271,6 +271,7 @@ std::string HelpMessage()
*/ */
bool AppInit2() bool AppInit2()
{ {
// ********************************************************* Step 1: setup
#ifdef _MSC_VER #ifdef _MSC_VER
// Turn off microsoft heap dump noise // Turn off microsoft heap dump noise
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
@ -294,12 +295,35 @@ bool AppInit2()
sigaction(SIGHUP, &sa, NULL); sigaction(SIGHUP, &sa, NULL);
#endif #endif
// ********************************************************* Step 2: parameter interactions
fTestNet = GetBoolArg("-testnet"); fTestNet = GetBoolArg("-testnet");
if (fTestNet) if (fTestNet)
{ {
SoftSetBoolArg("-irc", true); SoftSetBoolArg("-irc", true);
} }
if (mapArgs.count("-connect"))
SoftSetBoolArg("-dnsseed", false);
// even in Tor mode, if -bind is specified, you really want -listen
if (mapArgs.count("-bind"))
SoftSetBoolArg("-listen", true);
bool fTor = (fUseProxy && addrProxy.GetPort() == 9050);
if (fTor)
{
// Use SoftSetBoolArg here so user can override any of these if they wish.
// Note: the GetBoolArg() calls for all of these must happen later.
SoftSetBoolArg("-listen", false);
SoftSetBoolArg("-irc", false);
SoftSetBoolArg("-proxydns", true);
SoftSetBoolArg("-upnp", false);
SoftSetBoolArg("-discover", false);
}
// ********************************************************* Step 3: parameter-to-internal-flags
fDebug = GetBoolArg("-debug"); fDebug = GetBoolArg("-debug");
fDetachDB = GetBoolArg("-detachdb", false); fDetachDB = GetBoolArg("-detachdb", false);
@ -322,6 +346,38 @@ bool AppInit2()
fPrintToDebugger = GetBoolArg("-printtodebugger"); fPrintToDebugger = GetBoolArg("-printtodebugger");
fLogTimestamps = GetBoolArg("-logtimestamps"); fLogTimestamps = GetBoolArg("-logtimestamps");
if (mapArgs.count("-timeout"))
{
int nNewTimeout = GetArg("-timeout", 5000);
if (nNewTimeout > 0 && nNewTimeout < 600000)
nConnectTimeout = nNewTimeout;
}
// Continue to put "/P2SH/" in the coinbase to monitor
// BIP16 support.
// This can be removed eventually...
const char* pszP2SH = "/P2SH/";
COINBASE_FLAGS << std::vector<unsigned char>(pszP2SH, pszP2SH+strlen(pszP2SH));
if (mapArgs.count("-paytxfee"))
{
if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee))
return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s'"), mapArgs["-paytxfee"].c_str()));
if (nTransactionFee > 0.25 * COIN)
InitWarning(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."));
}
// ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log
// Make sure only a single Bitcoin process is using the data directory.
boost::filesystem::path pathLockFile = GetDataDir() / ".lock";
FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist.
if (file) fclose(file);
static boost::interprocess::file_lock lock(pathLockFile.string().c_str());
if (!lock.try_lock())
return InitError(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().string().c_str()));
#if !defined(WIN32) && !defined(QT_GUI) #if !defined(WIN32) && !defined(QT_GUI)
if (fDaemon) if (fDaemon)
{ {
@ -349,43 +405,104 @@ bool AppInit2()
printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
printf("Bitcoin version %s (%s)\n", FormatFullVersion().c_str(), CLIENT_DATE.c_str()); printf("Bitcoin version %s (%s)\n", FormatFullVersion().c_str(), CLIENT_DATE.c_str());
printf("Default data directory %s\n", GetDefaultDataDir().string().c_str()); printf("Default data directory %s\n", GetDefaultDataDir().string().c_str());
std::ostringstream strErrors;
if (GetBoolArg("-loadblockindextest")) if (fDaemon)
fprintf(stdout, "Bitcoin server starting\n");
int64 nStart;
// ********************************************************* Step 5: network initialization
if (mapArgs.count("-proxy"))
{ {
CTxDB txdb("r"); fUseProxy = true;
txdb.LoadBlockIndex(); addrProxy = CService(mapArgs["-proxy"], 9050);
PrintBlockTree(); if (!addrProxy.IsValid())
return false; return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"].c_str()));
} }
// Make sure only a single Bitcoin process is using the data directory. if (mapArgs.count("-noproxy"))
boost::filesystem::path pathLockFile = GetDataDir() / ".lock"; {
FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist. BOOST_FOREACH(std::string snet, mapMultiArgs["-noproxy"]) {
if (file) fclose(file); enum Network net = ParseNetwork(snet);
static boost::interprocess::file_lock lock(pathLockFile.string().c_str()); if (net == NET_UNROUTABLE)
if (!lock.try_lock()) return InitError(strprintf(_("Unknown network specified in -noproxy: '%s'"), snet.c_str()));
return InitError(strprintf(_("Cannot obtain a lock on data directory %s. Bitcoin is probably already running."), GetDataDir().string().c_str())); SetNoProxy(net);
}
}
std::ostringstream strErrors; fNameLookup = GetBoolArg("-dns");
// fProxyNameLookup = GetBoolArg("-proxydns");
// Load data files if (fProxyNameLookup)
// fNameLookup = true;
if (fDaemon) fNoListen = !GetBoolArg("-listen", true);
fprintf(stdout, "Bitcoin server starting\n"); nSocksVersion = GetArg("-socks", 5);
int64 nStart; if (nSocksVersion != 4 && nSocksVersion != 5)
return InitError(strprintf(_("Unknown -socks proxy version requested: %i"), nSocksVersion));
uiInterface.InitMessage(_("Loading addresses...")); if (mapArgs.count("-onlynet")) {
printf("Loading addresses...\n"); std::set<enum Network> nets;
nStart = GetTimeMillis(); BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) {
enum Network net = ParseNetwork(snet);
if (net == NET_UNROUTABLE)
return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet.c_str()));
nets.insert(net);
}
for (int n = 0; n < NET_MAX; n++) {
enum Network net = (enum Network)n;
if (!nets.count(net))
SetLimited(net);
}
}
BOOST_FOREACH(string strDest, mapMultiArgs["-seednode"])
AddOneShot(strDest);
bool fBound = false;
if (!fNoListen)
{ {
CAddrDB adb; std::string strError;
if (!adb.Read(addrman)) if (mapArgs.count("-bind")) {
printf("Invalid or missing peers.dat; recreating\n"); BOOST_FOREACH(std::string strBind, mapMultiArgs["-bind"]) {
CService addrBind;
if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false))
return InitError(strprintf(_("Cannot resolve -bind address: '%s'"), strBind.c_str()));
fBound |= Bind(addrBind);
}
} else {
struct in_addr inaddr_any;
inaddr_any.s_addr = INADDR_ANY;
if (!IsLimited(NET_IPV4))
fBound |= Bind(CService(inaddr_any, GetListenPort()));
#ifdef USE_IPV6
if (!IsLimited(NET_IPV6))
fBound |= Bind(CService(in6addr_any, GetListenPort()));
#endif
}
if (!fBound)
return InitError(_("Not listening on any port"));
} }
printf("Loaded %i addresses from peers.dat %"PRI64d"ms\n", if (mapArgs.count("-externalip"))
addrman.size(), GetTimeMillis() - nStart); {
BOOST_FOREACH(string strAddr, mapMultiArgs["-externalip"]) {
CService addrLocal(strAddr, GetListenPort(), fNameLookup);
if (!addrLocal.IsValid())
return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr.c_str()));
AddLocal(CService(strAddr, GetListenPort(), fNameLookup), LOCAL_MANUAL);
}
}
// ********************************************************* Step 6: load blockchain
if (GetBoolArg("-loadblockindextest"))
{
CTxDB txdb("r");
txdb.LoadBlockIndex();
PrintBlockTree();
return false;
}
uiInterface.InitMessage(_("Loading block index...")); uiInterface.InitMessage(_("Loading block index..."));
printf("Loading block index...\n"); printf("Loading block index...\n");
@ -403,16 +520,37 @@ bool AppInit2()
} }
printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart); printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart);
if (mapArgs.count("-loadblock")) if (GetBoolArg("-printblockindex") || GetBoolArg("-printblocktree"))
{ {
BOOST_FOREACH(string strFile, mapMultiArgs["-loadblock"]) PrintBlockTree();
return false;
}
if (mapArgs.count("-printblock"))
{
string strMatch = mapArgs["-printblock"];
int nFound = 0;
for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
{ {
FILE *file = fopen(strFile.c_str(), "rb"); uint256 hash = (*mi).first;
if (file) if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0)
LoadExternalBlockFile(file); {
CBlockIndex* pindex = (*mi).second;
CBlock block;
block.ReadFromDisk(pindex);
block.BuildMerkleTree();
block.print();
printf("\n");
nFound++;
}
} }
if (nFound == 0)
printf("No blocks matching %s were found\n", strMatch.c_str());
return false;
} }
// ********************************************************* Step 7: load wallet
uiInterface.InitMessage(_("Loading wallet...")); uiInterface.InitMessage(_("Loading wallet..."));
printf("Loading wallet...\n"); printf("Loading wallet...\n");
nStart = GetTimeMillis(); nStart = GetTimeMillis();
@ -488,192 +626,64 @@ bool AppInit2()
printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart); printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
} }
uiInterface.InitMessage(_("Done loading")); // ********************************************************* Step 8: import blocks
printf("Done loading\n");
//// debug print
printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
printf("nBestHeight = %d\n", nBestHeight);
printf("setKeyPool.size() = %d\n", pwalletMain->setKeyPool.size());
printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size());
printf("mapAddressBook.size() = %d\n", pwalletMain->mapAddressBook.size());
if (!strErrors.str().empty())
return InitError(strErrors.str());
// Add wallet transactions that aren't already in a block to mapTransactions
pwalletMain->ReacceptWalletTransactions();
// Note: Bitcoin-Qt stores several settings in the wallet, so we want
// to load the wallet BEFORE parsing command-line arguments, so
// the command-line/bitcoin.conf settings override GUI setting.
// if (mapArgs.count("-loadblock"))
// Parameters
//
if (GetBoolArg("-printblockindex") || GetBoolArg("-printblocktree"))
{
PrintBlockTree();
return false;
}
if (mapArgs.count("-timeout"))
{
int nNewTimeout = GetArg("-timeout", 5000);
if (nNewTimeout > 0 && nNewTimeout < 600000)
nConnectTimeout = nNewTimeout;
}
if (mapArgs.count("-printblock"))
{ {
string strMatch = mapArgs["-printblock"]; BOOST_FOREACH(string strFile, mapMultiArgs["-loadblock"])
int nFound = 0;
for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
{ {
uint256 hash = (*mi).first; FILE *file = fopen(strFile.c_str(), "rb");
if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0) if (file)
{ LoadExternalBlockFile(file);
CBlockIndex* pindex = (*mi).second;
CBlock block;
block.ReadFromDisk(pindex);
block.BuildMerkleTree();
block.print();
printf("\n");
nFound++;
}
}
if (nFound == 0)
printf("No blocks matching %s were found\n", strMatch.c_str());
return false;
}
if (mapArgs.count("-proxy"))
{
fUseProxy = true;
addrProxy = CService(mapArgs["-proxy"], 9050);
if (!addrProxy.IsValid())
return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"].c_str()));
}
if (mapArgs.count("-noproxy"))
{
BOOST_FOREACH(std::string snet, mapMultiArgs["-noproxy"]) {
enum Network net = ParseNetwork(snet);
if (net == NET_UNROUTABLE)
return InitError(strprintf(_("Unknown network specified in -noproxy: '%s'"), snet.c_str()));
SetNoProxy(net);
}
}
if (mapArgs.count("-connect"))
SoftSetBoolArg("-dnsseed", false);
// even in Tor mode, if -bind is specified, you really want -listen
if (mapArgs.count("-bind"))
SoftSetBoolArg("-listen", true);
bool fTor = (fUseProxy && addrProxy.GetPort() == 9050);
if (fTor)
{
// Use SoftSetBoolArg here so user can override any of these if they wish.
// Note: the GetBoolArg() calls for all of these must happen later.
SoftSetBoolArg("-listen", false);
SoftSetBoolArg("-irc", false);
SoftSetBoolArg("-proxydns", true);
SoftSetBoolArg("-upnp", false);
SoftSetBoolArg("-discover", false);
}
if (mapArgs.count("-onlynet")) {
std::set<enum Network> nets;
BOOST_FOREACH(std::string snet, mapMultiArgs["-onlynet"]) {
enum Network net = ParseNetwork(snet);
if (net == NET_UNROUTABLE)
return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet.c_str()));
nets.insert(net);
}
for (int n = 0; n < NET_MAX; n++) {
enum Network net = (enum Network)n;
if (!nets.count(net))
SetLimited(net);
} }
} }
fNameLookup = GetBoolArg("-dns"); // ********************************************************* Step 9: load peers
fProxyNameLookup = GetBoolArg("-proxydns");
if (fProxyNameLookup)
fNameLookup = true;
fNoListen = !GetBoolArg("-listen", true);
nSocksVersion = GetArg("-socks", 5);
if (nSocksVersion != 4 && nSocksVersion != 5)
return InitError(strprintf(_("Unknown -socks proxy version requested: %i"), nSocksVersion));
BOOST_FOREACH(string strDest, mapMultiArgs["-seednode"]) uiInterface.InitMessage(_("Loading addresses..."));
AddOneShot(strDest); printf("Loading addresses...\n");
nStart = GetTimeMillis();
// Continue to put "/P2SH/" in the coinbase to monitor
// BIP16 support.
// This can be removed eventually...
const char* pszP2SH = "/P2SH/";
COINBASE_FLAGS << std::vector<unsigned char>(pszP2SH, pszP2SH+strlen(pszP2SH));
bool fBound = false;
if (!fNoListen)
{ {
std::string strError; CAddrDB adb;
if (mapArgs.count("-bind")) { if (!adb.Read(addrman))
BOOST_FOREACH(std::string strBind, mapMultiArgs["-bind"]) { printf("Invalid or missing peers.dat; recreating\n");
CService addrBind;
if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false))
return InitError(strprintf(_("Cannot resolve -bind address: '%s'"), strBind.c_str()));
fBound |= Bind(addrBind);
}
} else {
struct in_addr inaddr_any;
inaddr_any.s_addr = INADDR_ANY;
if (!IsLimited(NET_IPV4))
fBound |= Bind(CService(inaddr_any, GetListenPort()));
#ifdef USE_IPV6
if (!IsLimited(NET_IPV6))
fBound |= Bind(CService(in6addr_any, GetListenPort()));
#endif
}
if (!fBound)
return InitError(_("Not listening on any port"));
} }
if (mapArgs.count("-externalip")) printf("Loaded %i addresses from peers.dat %"PRI64d"ms\n",
{ addrman.size(), GetTimeMillis() - nStart);
BOOST_FOREACH(string strAddr, mapMultiArgs["-externalip"]) {
CService addrLocal(strAddr, GetListenPort(), fNameLookup);
if (!addrLocal.IsValid())
return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr.c_str()));
AddLocal(CService(strAddr, GetListenPort(), fNameLookup), LOCAL_MANUAL);
}
}
if (mapArgs.count("-paytxfee")) // ********************************************************* Step 10: start node
{
if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee))
return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s'"), mapArgs["-paytxfee"].c_str()));
if (nTransactionFee > 0.25 * COIN)
InitWarning(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."));
}
//
// Start the node
//
if (!CheckDiskSpace()) if (!CheckDiskSpace())
return false; return false;
RandAddSeedPerfmon(); RandAddSeedPerfmon();
//// debug print
printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
printf("nBestHeight = %d\n", nBestHeight);
printf("setKeyPool.size() = %d\n", pwalletMain->setKeyPool.size());
printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size());
printf("mapAddressBook.size() = %d\n", pwalletMain->mapAddressBook.size());
if (!CreateThread(StartNode, NULL)) if (!CreateThread(StartNode, NULL))
InitError(_("Error: could not start node")); InitError(_("Error: could not start node"));
if (fServer) if (fServer)
CreateThread(ThreadRPCServer, NULL); CreateThread(ThreadRPCServer, NULL);
// ********************************************************* Step 11: finished
uiInterface.InitMessage(_("Done loading"));
printf("Done loading\n");
if (!strErrors.str().empty())
return InitError(strErrors.str());
// Add wallet transactions that aren't already in a block to mapTransactions
pwalletMain->ReacceptWalletTransactions();
#if !defined(QT_GUI) #if !defined(QT_GUI)
// Loop until process is exit()ed from shutdown() function, // Loop until process is exit()ed from shutdown() function,
// called from ThreadRPCServer thread when a "stop" command is received. // called from ThreadRPCServer thread when a "stop" command is received.

Loading…
Cancel
Save