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 | 398 ++++++++++++++++++++++++++------------------------- 1 file changed, 204 insertions(+), 194 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 4e193ffe..69f780f4 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,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("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 (GetBoolArg("-loadblockindextest")) + if (fDaemon) + fprintf(stdout, "Bitcoin server starting\n"); + + int64 nStart; + + // ********************************************************* Step 5: network initialization + + if (mapArgs.count("-proxy")) { - CTxDB txdb("r"); - txdb.LoadBlockIndex(); - PrintBlockTree(); - return false; + fUseProxy = true; + addrProxy = CService(mapArgs["-proxy"], 9050); + if (!addrProxy.IsValid()) + return InitError(strprintf(_("Invalid -proxy address: '%s'"), mapArgs["-proxy"].c_str())); } - // 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 (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); + } + } - std::ostringstream strErrors; - // - // Load data files - // - if (fDaemon) - fprintf(stdout, "Bitcoin server starting\n"); - int64 nStart; + 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)); - uiInterface.InitMessage(_("Loading addresses...")); - printf("Loading addresses...\n"); - nStart = GetTimeMillis(); + 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) { - CAddrDB adb; - if (!adb.Read(addrman)) - printf("Invalid or missing peers.dat; recreating\n"); + 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")); } - printf("Loaded %i addresses from peers.dat %"PRI64d"ms\n", - addrman.size(), GetTimeMillis() - nStart); + 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")) + { + CTxDB txdb("r"); + txdb.LoadBlockIndex(); + PrintBlockTree(); + return false; + } uiInterface.InitMessage(_("Loading block index...")); printf("Loading block index...\n"); @@ -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"]) + PrintBlockTree(); + return false; + } + + if (mapArgs.count("-printblock")) + { + string strMatch = mapArgs["-printblock"]; + int nFound = 0; + for (map::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) { - FILE *file = fopen(strFile.c_str(), "rb"); - if (file) - LoadExternalBlockFile(file); + 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,192 +626,64 @@ bool AppInit2() printf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart); } - uiInterface.InitMessage(_("Done loading")); - 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. + // ********************************************************* Step 8: import blocks - // - // 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")) + if (mapArgs.count("-loadblock")) { - string strMatch = mapArgs["-printblock"]; - int nFound = 0; - for (map::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi) + BOOST_FOREACH(string strFile, mapMultiArgs["-loadblock"]) { - 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); + FILE *file = fopen(strFile.c_str(), "rb"); + if (file) + LoadExternalBlockFile(file); } } - 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)); + // ********************************************************* Step 9: load peers - 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)); + uiInterface.InitMessage(_("Loading addresses...")); + printf("Loading addresses...\n"); + nStart = GetTimeMillis(); - 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")); + CAddrDB adb; + if (!adb.Read(addrman)) + printf("Invalid or missing peers.dat; recreating\n"); } - 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); - } - } + printf("Loaded %i addresses from peers.dat %"PRI64d"ms\n", + addrman.size(), GetTimeMillis() - nStart); - 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 10: start node - // - // Start the node - // if (!CheckDiskSpace()) return false; 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)) 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.