Merge pull request #1369 from sipa/bootorder

Reorder AppInit2
This commit is contained in:
Pieter Wuille 2012-05-22 13:54:46 -07:00
commit fa638ec8af

View file

@ -275,6 +275,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);
@ -304,12 +305,35 @@ bool AppInit2()
sigaction(SIGHUP, &sa_hup, NULL); sigaction(SIGHUP, &sa_hup, 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);
@ -332,6 +356,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)
{ {
@ -359,6 +415,96 @@ 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 (fDaemon)
fprintf(stdout, "Bitcoin server starting\n");
int64 nStart;
// ********************************************************* Step 5: network initialization
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);
}
}
fNameLookup = GetBoolArg("-dns");
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));
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);
}
}
BOOST_FOREACH(string strDest, mapMultiArgs["-seednode"])
AddOneShot(strDest);
bool fBound = false;
if (!fNoListen)
{
std::string strError;
if (mapArgs.count("-bind")) {
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"));
}
if (mapArgs.count("-externalip"))
{
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")) if (GetBoolArg("-loadblockindextest"))
{ {
@ -368,35 +514,6 @@ bool AppInit2()
return false; return false;
} }
// 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()));
std::ostringstream strErrors;
//
// Load data files
//
if (fDaemon)
fprintf(stdout, "Bitcoin server starting\n");
int64 nStart;
uiInterface.InitMessage(_("Loading addresses..."));
printf("Loading addresses...\n");
nStart = GetTimeMillis();
{
CAddrDB adb;
if (!adb.Read(addrman))
printf("Invalid or missing peers.dat; recreating\n");
}
printf("Loaded %i addresses from peers.dat %"PRI64d"ms\n",
addrman.size(), GetTimeMillis() - nStart);
uiInterface.InitMessage(_("Loading block index...")); uiInterface.InitMessage(_("Loading block index..."));
printf("Loading block index...\n"); printf("Loading block index...\n");
nStart = GetTimeMillis(); nStart = GetTimeMillis();
@ -413,16 +530,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;
FILE *file = fopen(strFile.c_str(), "rb");
if (file)
LoadExternalBlockFile(file);
}
} }
if (mapArgs.count("-printblock"))
{
string strMatch = mapArgs["-printblock"];
int nFound = 0;
for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
{
uint256 hash = (*mi).first;
if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0)
{
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();
@ -498,8 +636,39 @@ 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");
if (mapArgs.count("-loadblock"))
{
BOOST_FOREACH(string strFile, mapMultiArgs["-loadblock"])
{
FILE *file = fopen(strFile.c_str(), "rb");
if (file)
LoadExternalBlockFile(file);
}
}
// ********************************************************* Step 9: load peers
uiInterface.InitMessage(_("Loading addresses..."));
printf("Loading addresses...\n");
nStart = GetTimeMillis();
{
CAddrDB adb;
if (!adb.Read(addrman))
printf("Invalid or missing peers.dat; recreating\n");
}
printf("Loaded %i addresses from peers.dat %"PRI64d"ms\n",
addrman.size(), GetTimeMillis() - nStart);
// ********************************************************* Step 10: start node
if (!CheckDiskSpace())
return false;
RandAddSeedPerfmon();
//// debug print //// debug print
printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size()); printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size());
@ -508,182 +677,23 @@ bool AppInit2()
printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size()); printf("mapWallet.size() = %d\n", pwalletMain->mapWallet.size());
printf("mapAddressBook.size() = %d\n", pwalletMain->mapAddressBook.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.
//
// 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"];
int nFound = 0;
for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
{
uint256 hash = (*mi).first;
if (strncmp(hash.ToString().c_str(), strMatch.c_str(), strMatch.size()) == 0)
{
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");
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"])
AddOneShot(strDest);
// 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;
if (mapArgs.count("-bind")) {
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"));
}
if (mapArgs.count("-externalip"))
{
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"))
{
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())
return false;
RandAddSeedPerfmon();
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.