From 7d80d2e3d7ecceb5a99fef357b118949f6dd8a79 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 21 May 2012 16:47:29 +0200 Subject: [PATCH] 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). --- src/init.cpp | 426 ++++++++++++++++++++++++++------------------------- 1 file changed, 218 insertions(+), 208 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 4e193ffe3..69f780f4d 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -271,6 +271,7 @@ std::string HelpMessage() */ bool AppInit2() { + // ********************************************************* Step 1: setup #ifdef _MSC_VER // Turn off microsoft heap dump noise _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); @@ -294,12 +295,35 @@ bool AppInit2() sigaction(SIGHUP, &sa, NULL); #endif + // ********************************************************* Step 2: parameter interactions + fTestNet = GetBoolArg("-testnet"); if (fTestNet) { 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"); fDetachDB = GetBoolArg("-detachdb", false); @@ -322,6 +346,38 @@ bool AppInit2() fPrintToDebugger = GetBoolArg("-printtodebugger"); 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(pszP2SH, pszP2SH+strlen(pszP2SH)); + + + if (mapArgs.count("-paytxfee")) + { + if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee)) + return InitError(strprintf(_("Invalid amount for -paytxfee=: '%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 (fDaemon) { @@ -349,6 +405,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("Bitcoin version %s (%s)\n", FormatFullVersion().c_str(), CLIENT_DATE.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 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")) { @@ -358,35 +504,6 @@ bool AppInit2() 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...")); printf("Loading block index...\n"); nStart = GetTimeMillis(); @@ -403,16 +520,37 @@ bool AppInit2() } printf(" block index %15"PRI64d"ms\n", GetTimeMillis() - nStart); - if (mapArgs.count("-loadblock")) + if (GetBoolArg("-printblockindex") || GetBoolArg("-printblocktree")) { - BOOST_FOREACH(string strFile, mapMultiArgs["-loadblock"]) - { - FILE *file = fopen(strFile.c_str(), "rb"); - if (file) - LoadExternalBlockFile(file); - } + PrintBlockTree(); + return false; } + if (mapArgs.count("-printblock")) + { + string strMatch = mapArgs["-printblock"]; + int nFound = 0; + for (map::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...")); printf("Loading wallet...\n"); nStart = GetTimeMillis(); @@ -488,8 +626,39 @@ bool AppInit2() printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart); } - uiInterface.InitMessage(_("Done loading")); - printf("Done loading\n"); + // ********************************************************* Step 8: import blocks + + 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 printf("mapBlockIndex.size() = %d\n", mapBlockIndex.size()); @@ -498,182 +667,23 @@ bool AppInit2() 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. - - // - // 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::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 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(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=: '%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)) InitError(_("Error: could not start node")); if (fServer) 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) // Loop until process is exit()ed from shutdown() function, // called from ThreadRPCServer thread when a "stop" command is received.