diff --git a/src/init.cpp b/src/init.cpp
index 5d4d1d38c..4d563d04b 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1,2375 +1,2375 @@
 // Copyright (c) 2009-2010 Satoshi Nakamoto
 // Copyright (c) 2009-2016 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #if defined(HAVE_CONFIG_H)
 #include "config/bitcoin-config.h"
 #endif
 
 #include "init.h"
 
 #include "addrman.h"
 #include "amount.h"
 #include "chain.h"
 #include "chainparams.h"
 #include "checkpoints.h"
 #include "compat/sanity.h"
 #include "config.h"
 #include "consensus/validation.h"
 #include "diskblockpos.h"
 #include "fs.h"
 #include "httprpc.h"
 #include "httpserver.h"
 #include "key.h"
 #include "miner.h"
 #include "net.h"
 #include "net_processing.h"
 #include "netbase.h"
 #include "policy/policy.h"
 #include "rpc/register.h"
 #include "rpc/server.h"
 #include "scheduler.h"
 #include "script/scriptcache.h"
 #include "script/sigcache.h"
 #include "script/standard.h"
 #include "timedata.h"
 #include "torcontrol.h"
 #include "txdb.h"
 #include "txmempool.h"
 #include "ui_interface.h"
 #include "util.h"
 #include "utilmoneystr.h"
 #include "validation.h"
 #include "validationinterface.h"
 #ifdef ENABLE_WALLET
 #include "wallet/rpcdump.h"
 #endif
 #include "walletinitinterface.h"
 #include "warnings.h"
 
 #include <cstdint>
 #include <cstdio>
 #include <memory>
 
 #ifndef WIN32
 #include <csignal>
 #endif
 
 #include <boost/algorithm/string/classification.hpp>
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/algorithm/string/split.hpp>
 #include <boost/bind.hpp>
 #include <boost/interprocess/sync/file_lock.hpp>
 #include <boost/thread.hpp>
 
 #if ENABLE_ZMQ
 #include "zmq/zmqnotificationinterface.h"
 #endif
 
 static const bool DEFAULT_PROXYRANDOMIZE = true;
 static const bool DEFAULT_REST_ENABLE = false;
 static const bool DEFAULT_STOPAFTERBLOCKIMPORT = false;
 
 std::unique_ptr<CConnman> g_connman;
 std::unique_ptr<PeerLogicValidation> peerLogic;
 
 #if !(ENABLE_WALLET)
 class DummyWalletInit : public WalletInitInterface {
 public:
     std::string GetHelpString(bool showDebug) override { return std::string{}; }
     bool ParameterInteraction() override { return true; }
     void RegisterRPC(CRPCTable &) override {}
     bool Verify(const CChainParams &chainParams) override { return true; }
     bool Open(const CChainParams &chainParams) override { return true; }
     void Start(CScheduler &scheduler) override {}
     void Flush() override {}
     void Stop() override {}
     void Close() override {}
 };
 
 static DummyWalletInit g_dummy_wallet_init;
 WalletInitInterface *const g_wallet_init_interface = &g_dummy_wallet_init;
 #endif
 
 #if ENABLE_ZMQ
 static CZMQNotificationInterface *pzmqNotificationInterface = nullptr;
 #endif
 
 #ifdef WIN32
 // Win32 LevelDB doesn't use filedescriptors, and the ones used for accessing
 // block files don't count towards the fd_set size limit anyway.
 #define MIN_CORE_FILEDESCRIPTORS 0
 #else
 #define MIN_CORE_FILEDESCRIPTORS 150
 #endif
 
 //////////////////////////////////////////////////////////////////////////////
 //
 // Shutdown
 //
 
 //
 // Thread management and startup/shutdown:
 //
 // The network-processing threads are all part of a thread group created by
 // AppInit() or the Qt main() function.
 //
 // A clean exit happens when StartShutdown() or the SIGTERM signal handler sets
 // fRequestShutdown, which triggers the DetectShutdownThread(), which interrupts
 // the main thread group. DetectShutdownThread() then exits, which causes
 // AppInit() to continue (it .joins the shutdown thread). Shutdown() is then
 // called to clean up database connections, and stop other threads that should
 // only be stopped after the main network-processing threads have exited.
 //
 // Note that if running -daemon the parent process returns from AppInit2 before
 // adding any threads to the threadGroup, so .join_all() returns immediately and
 // the parent exits from main().
 //
 // Shutdown for Qt is very similar, only it uses a QTimer to detect
 // fRequestShutdown getting set, and then does the normal Qt shutdown thing.
 //
 
 std::atomic<bool> fRequestShutdown(false);
 std::atomic<bool> fDumpMempoolLater(false);
 
 void StartShutdown() {
     fRequestShutdown = true;
 }
 bool ShutdownRequested() {
     return fRequestShutdown;
 }
 
 /**
  * This is a minimally invasive approach to shutdown on LevelDB read errors from
  * the chainstate, while keeping user interface out of the common library, which
  * is shared between bitcoind, and bitcoin-qt and non-server tools.
  */
 class CCoinsViewErrorCatcher final : public CCoinsViewBacked {
 public:
     explicit CCoinsViewErrorCatcher(CCoinsView *view)
         : CCoinsViewBacked(view) {}
     bool GetCoin(const COutPoint &outpoint, Coin &coin) const override {
         try {
             return CCoinsViewBacked::GetCoin(outpoint, coin);
         } catch (const std::runtime_error &e) {
             uiInterface.ThreadSafeMessageBox(
                 _("Error reading from database, shutting down."), "",
                 CClientUIInterface::MSG_ERROR);
             LogPrintf("Error reading from database: %s\n", e.what());
             // Starting the shutdown sequence and returning false to the caller
             // would be interpreted as 'entry not found' (as opposed to unable
             // to read data), and could lead to invalid interpretation. Just
             // exit immediately, as we can't continue anyway, and all writes
             // should be atomic.
             abort();
         }
     }
     // Writes do not need similar protection, as failure to write is handled by
     // the caller.
 };
 
 static std::unique_ptr<CCoinsViewErrorCatcher> pcoinscatcher;
 static std::unique_ptr<ECCVerifyHandle> globalVerifyHandle;
 
 static boost::thread_group threadGroup;
 static CScheduler scheduler;
 
 void Interrupt() {
     InterruptHTTPServer();
     InterruptHTTPRPC();
     InterruptRPC();
     InterruptREST();
     InterruptTorControl();
     InterruptMapPort();
     if (g_connman) {
         g_connman->Interrupt();
     }
 }
 
 void Shutdown() {
     LogPrintf("%s: In progress...\n", __func__);
     static CCriticalSection cs_Shutdown;
     TRY_LOCK(cs_Shutdown, lockShutdown);
     if (!lockShutdown) {
         return;
     }
 
     /// Note: Shutdown() must be able to handle cases in which AppInit2() failed
     /// part of the way, for example if the data directory was found to be
     /// locked. Be sure that anything that writes files or flushes caches only
     /// does this if the respective module was initialized.
     RenameThread("bitcoin-shutoff");
     g_mempool.AddTransactionsUpdated(1);
 
     StopHTTPRPC();
     StopREST();
     StopRPC();
     StopHTTPServer();
     g_wallet_init_interface->Flush();
     StopMapPort();
 
     // Because these depend on each-other, we make sure that neither can be
     // using the other before destroying them.
     if (peerLogic) {
         UnregisterValidationInterface(peerLogic.get());
     }
     if (g_connman) {
         g_connman->Stop();
     }
     peerLogic.reset();
     g_connman.reset();
 
     StopTorControl();
 
     // After everything has been shut down, but before things get flushed, stop
     // the CScheduler/checkqueue threadGroup
     threadGroup.interrupt_all();
     threadGroup.join_all();
 
     if (fDumpMempoolLater &&
         gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
         DumpMempool();
     }
 
     // FlushStateToDisk generates a SetBestChain callback, which we should avoid
     // missing
     if (pcoinsTip != nullptr) {
         FlushStateToDisk();
     }
 
     // After there are no more peers/RPC left to give us new data which may
     // generate CValidationInterface callbacks, flush them...
     GetMainSignals().FlushBackgroundCallbacks();
 
     // Any future callbacks will be dropped. This should absolutely be safe - if
     // missing a callback results in an unrecoverable situation, unclean
     // shutdown would too. The only reason to do the above flushes is to let the
     // wallet catch up with our current chain to avoid any strange pruning edge
     // cases and make next startup faster by avoiding rescan.
 
     {
         LOCK(cs_main);
         if (pcoinsTip != nullptr) {
             FlushStateToDisk();
         }
         pcoinsTip.reset();
         pcoinscatcher.reset();
         pcoinsdbview.reset();
         pblocktree.reset();
     }
     g_wallet_init_interface->Stop();
 
 #if ENABLE_ZMQ
     if (pzmqNotificationInterface) {
         UnregisterValidationInterface(pzmqNotificationInterface);
         delete pzmqNotificationInterface;
         pzmqNotificationInterface = nullptr;
     }
 #endif
 
 #ifndef WIN32
     try {
         fs::remove(GetPidFile());
     } catch (const fs::filesystem_error &e) {
         LogPrintf("%s: Unable to remove pidfile: %s\n", __func__, e.what());
     }
 #endif
     UnregisterAllValidationInterfaces();
     GetMainSignals().UnregisterBackgroundSignalScheduler();
     GetMainSignals().UnregisterWithMempoolSignals(g_mempool);
     g_wallet_init_interface->Close();
     globalVerifyHandle.reset();
     ECC_Stop();
     LogPrintf("%s: done\n", __func__);
 }
 
 /**
  * Signal handlers are very limited in what they are allowed to do, so:
  */
 void HandleSIGTERM(int) {
     fRequestShutdown = true;
 }
 
 void HandleSIGHUP(int) {
     GetLogger().m_reopen_file = true;
 }
 
 void OnRPCStarted() {
     uiInterface.NotifyBlockTip.connect(&RPCNotifyBlockChange);
 }
 
 void OnRPCStopped() {
     uiInterface.NotifyBlockTip.disconnect(&RPCNotifyBlockChange);
     RPCNotifyBlockChange(false, nullptr);
     g_best_block_cv.notify_all();
     LogPrint(BCLog::RPC, "RPC stopped.\n");
 }
 
 std::string HelpMessage(HelpMessageMode mode) {
     const auto defaultBaseParams =
         CreateBaseChainParams(CBaseChainParams::MAIN);
     const auto testnetBaseParams =
         CreateBaseChainParams(CBaseChainParams::TESTNET);
     const auto defaultChainParams = CreateChainParams(CBaseChainParams::MAIN);
     const auto testnetChainParams =
         CreateChainParams(CBaseChainParams::TESTNET);
     const bool showDebug = gArgs.GetBoolArg("-help-debug", false);
 
     // When adding new options to the categories, please keep and ensure
     // alphabetical ordering. Do not translate _(...) -help-debug options, Many
     // technical terms, and only a very small audience, so is unnecessary stress
     // to translators.
     std::string strUsage = HelpMessageGroup(_("Options:"));
     strUsage += HelpMessageOpt("-?", _("Print this help message and exit"));
     strUsage += HelpMessageOpt("-version", _("Print version and exit"));
     strUsage += HelpMessageOpt(
         "-alertnotify=<cmd>",
         _("Execute command when a relevant alert is received or we see a "
           "really long fork (%s in cmd is replaced by message)"));
     strUsage += HelpMessageOpt("-blocknotify=<cmd>",
                                _("Execute command when the best block changes "
                                  "(%s in cmd is replaced by block hash)"));
     if (showDebug) {
         strUsage += HelpMessageOpt(
             "-blocksonly",
             strprintf(
                 _("Whether to operate in a blocks only mode (default: %d)"),
                 DEFAULT_BLOCKSONLY));
     }
     strUsage += HelpMessageOpt(
         "-assumevalid=<hex>",
         strprintf(
             _("If this block is in the chain assume that it and its ancestors "
               "are valid and potentially skip their script verification (0 to "
               "verify all, default: %s, testnet: %s)"),
             defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(),
             testnetChainParams->GetConsensus().defaultAssumeValid.GetHex()));
     strUsage += HelpMessageOpt(
         "-conf=<file>", strprintf(_("Specify configuration file (default: %s)"),
                                   BITCOIN_CONF_FILENAME));
     if (mode == HelpMessageMode::BITCOIND) {
 #if HAVE_DECL_DAEMON
         strUsage += HelpMessageOpt(
             "-daemon",
             _("Run in the background as a daemon and accept commands"));
 #endif
     }
     strUsage += HelpMessageOpt("-datadir=<dir>", _("Specify data directory"));
     if (showDebug) {
         strUsage += HelpMessageOpt(
             "-dbbatchsize",
             strprintf(
                 "Maximum database write batch size in bytes (default: %u)",
                 nDefaultDbBatchSize));
     }
     strUsage += HelpMessageOpt(
         "-dbcache=<n>",
         strprintf(
             _("Set database cache size in megabytes (%d to %d, default: %d)"),
             nMinDbCache, nMaxDbCache, nDefaultDbCache));
     if (showDebug) {
         strUsage += HelpMessageOpt(
             "-feefilter", strprintf("Tell other nodes to filter invs to us by "
                                     "our mempool min fee (default: %d)",
                                     DEFAULT_FEEFILTER));
     }
     strUsage += HelpMessageOpt(
         "-finalizationdelay=<n>",
         strprintf("Set the minimum amount of time to wait between a "
                   "block header reception and the block finalization. "
                   "Unit is seconds (default: %d)",
                   DEFAULT_MIN_FINALIZATION_DELAY));
     strUsage += HelpMessageOpt(
         "-maxreorgdepth=<n>",
         strprintf("Configure at what depth blocks are considered final "
                   "(default: %d). Use -1 to disable.",
                   DEFAULT_MAX_REORG_DEPTH));
     strUsage += HelpMessageOpt(
         "-loadblock=<file>",
         _("Imports blocks from external blk000??.dat file on startup"));
     strUsage += HelpMessageOpt(
         "-debuglogfile=<file>",
         strprintf(
             _("Specify location of debug log file: this can be an absolute "
               "path or a path relative to the data directory (default: %s)"),
             DEFAULT_DEBUGLOGFILE));
     strUsage += HelpMessageOpt(
         "-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable "
                                         "transactions in memory (default: %u)"),
                                       DEFAULT_MAX_ORPHAN_TRANSACTIONS));
     strUsage += HelpMessageOpt("-maxmempool=<n>",
                                strprintf(_("Keep the transaction memory pool "
                                            "below <n> megabytes (default: %u)"),
                                          DEFAULT_MAX_MEMPOOL_SIZE));
     strUsage +=
         HelpMessageOpt("-mempoolexpiry=<n>",
                        strprintf(_("Do not keep transactions in the mempool "
                                    "longer than <n> hours (default: %u)"),
                                  DEFAULT_MEMPOOL_EXPIRY));
     if (showDebug) {
         strUsage += HelpMessageOpt(
             "-minimumchainwork=<hex>",
             strprintf(
                 "Minimum work assumed to exist on a valid chain in hex "
                 "(default: %s, testnet: %s)",
                 defaultChainParams->GetConsensus().nMinimumChainWork.GetHex(),
                 testnetChainParams->GetConsensus().nMinimumChainWork.GetHex()));
     }
     strUsage +=
         HelpMessageOpt("-persistmempool",
                        strprintf(_("Whether to save the mempool on shutdown "
                                    "and load on restart (default: %u)"),
                                  DEFAULT_PERSIST_MEMPOOL));
     strUsage += HelpMessageOpt(
         "-blockreconstructionextratxn=<n>",
         strprintf(_("Extra transactions to keep in memory for compact block "
                     "reconstructions (default: %u)"),
                   DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN));
     strUsage += HelpMessageOpt(
         "-par=<n>",
         strprintf(_("Set the number of script verification threads (%u to %d, "
                     "0 = auto, <0 = leave that many cores free, default: %d)"),
                   -GetNumCores(), MAX_SCRIPTCHECK_THREADS,
                   DEFAULT_SCRIPTCHECK_THREADS));
 #ifndef WIN32
     strUsage += HelpMessageOpt(
         "-pid=<file>",
         strprintf(_("Specify pid file (default: %s)"), BITCOIN_PID_FILENAME));
 #endif
     strUsage += HelpMessageOpt(
         "-prune=<n>",
         strprintf(
             _("Reduce storage requirements by enabling pruning (deleting) of "
               "old blocks. This allows the pruneblockchain RPC to be called to "
               "delete specific blocks, and enables automatic pruning of old "
               "blocks if a target size in MiB is provided. This mode is "
               "incompatible with -txindex and -rescan. "
               "Warning: Reverting this setting requires re-downloading the "
               "entire blockchain. "
               "(default: 0 = disable pruning blocks, 1 = allow manual pruning "
               "via RPC, >%u = automatically prune block files to stay under "
               "the specified target size in MiB)"),
             MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024));
     strUsage += HelpMessageOpt(
         "-reindex-chainstate",
         _("Rebuild chain state from the currently indexed blocks"));
     strUsage +=
         HelpMessageOpt("-reindex", _("Rebuild chain state and block index from "
                                      "the blk*.dat files on disk"));
 #ifndef WIN32
     strUsage += HelpMessageOpt(
         "-sysperms",
         _("Create new files with system default permissions, instead of umask "
           "077 (only effective with disabled wallet functionality)"));
 #endif
     strUsage += HelpMessageOpt(
         "-txindex", strprintf(_("Maintain a full transaction index, used by "
                                 "the getrawtransaction rpc call (default: %d)"),
                               DEFAULT_TXINDEX));
     strUsage += HelpMessageOpt(
         "-usecashaddr", _("Use Cash Address for destination encoding instead "
                           "of base58 (activate by default on Jan, 14)"));
 
     strUsage += HelpMessageGroup(_("Connection options:"));
     strUsage += HelpMessageOpt(
         "-addnode=<ip>",
         _("Add a node to connect to and attempt to keep the connection open "
           "(see the `addnode` RPC command help for more info)"));
     strUsage += HelpMessageOpt(
         "-banscore=<n>",
         strprintf(
             _("Threshold for disconnecting misbehaving peers (default: %u)"),
             DEFAULT_BANSCORE_THRESHOLD));
     strUsage += HelpMessageOpt(
         "-bantime=<n>", strprintf(_("Number of seconds to keep misbehaving "
                                     "peers from reconnecting (default: %u)"),
                                   DEFAULT_MISBEHAVING_BANTIME));
     strUsage += HelpMessageOpt("-bind=<addr>",
                                _("Bind to given address and always listen on "
                                  "it. Use [host]:port notation for IPv6"));
     strUsage += HelpMessageOpt(
         "-connect=<ip>", _("Connect only to the specified node(s); -connect=0 "
                            "disables automatic connections (the rules for this "
                            "peer are the same as for -addnode)"));
     strUsage += HelpMessageOpt("-discover",
                                _("Discover own IP addresses (default: 1 when "
                                  "listening and no -externalip or -proxy)"));
     strUsage += HelpMessageOpt(
         "-dns", _("Allow DNS lookups for -addnode, -seednode and -connect") +
                     " " + strprintf(_("(default: %d)"), DEFAULT_NAME_LOOKUP));
     strUsage += HelpMessageOpt(
         "-dnsseed", _("Query for peer addresses via DNS lookup, if low on "
                       "addresses (default: 1 unless -connect/-noconnect)"));
     strUsage += HelpMessageOpt("-externalip=<ip>",
                                _("Specify your own public address"));
     strUsage += HelpMessageOpt(
         "-forcednsseed",
         strprintf(
             _("Always query for peer addresses via DNS lookup (default: %d)"),
             DEFAULT_FORCEDNSSEED));
     strUsage +=
         HelpMessageOpt("-listen", _("Accept connections from outside (default: "
                                     "1 if no -proxy or -connect/-noconnect)"));
     strUsage += HelpMessageOpt(
         "-listenonion",
         strprintf(_("Automatically create Tor hidden service (default: %d)"),
                   DEFAULT_LISTEN_ONION));
     strUsage += HelpMessageOpt(
         "-maxconnections=<n>",
         strprintf(_("Maintain at most <n> connections to peers (default: %u)"),
                   DEFAULT_MAX_PEER_CONNECTIONS));
     strUsage +=
         HelpMessageOpt("-maxreceivebuffer=<n>",
                        strprintf(_("Maximum per-connection receive buffer, "
                                    "<n>*1000 bytes (default: %u)"),
                                  DEFAULT_MAXRECEIVEBUFFER));
     strUsage += HelpMessageOpt(
         "-maxsendbuffer=<n>", strprintf(_("Maximum per-connection send buffer, "
                                           "<n>*1000 bytes (default: %u)"),
                                         DEFAULT_MAXSENDBUFFER));
     strUsage += HelpMessageOpt(
         "-maxtimeadjustment",
         strprintf(_("Maximum allowed median peer time offset adjustment. Local "
                     "perspective of time may be influenced by peers forward or "
                     "backward by this amount. (default: %u seconds)"),
                   DEFAULT_MAX_TIME_ADJUSTMENT));
     strUsage +=
         HelpMessageOpt("-onion=<ip:port>",
                        strprintf(_("Use separate SOCKS5 proxy to reach peers "
                                    "via Tor hidden services (default: %s)"),
                                  "-proxy"));
     strUsage += HelpMessageOpt(
         "-onlynet=<net>",
         _("Only connect to nodes in network <net> (ipv4, ipv6 or onion)"));
     strUsage +=
         HelpMessageOpt("-permitbaremultisig",
                        strprintf(_("Relay non-P2SH multisig (default: %d)"),
                                  DEFAULT_PERMIT_BAREMULTISIG));
     strUsage += HelpMessageOpt(
         "-peerbloomfilters",
         strprintf(_("Support filtering of blocks and transaction with bloom "
                     "filters (default: %d)"),
                   DEFAULT_PEERBLOOMFILTERS));
     strUsage += HelpMessageOpt(
         "-port=<port>",
         strprintf(
             _("Listen for connections on <port> (default: %u or testnet: %u)"),
             defaultChainParams->GetDefaultPort(),
             testnetChainParams->GetDefaultPort()));
     strUsage +=
         HelpMessageOpt("-proxy=<ip:port>", _("Connect through SOCKS5 proxy"));
     strUsage += HelpMessageOpt(
         "-proxyrandomize",
         strprintf(_("Randomize credentials for every proxy connection. This "
                     "enables Tor stream isolation (default: %d)"),
                   DEFAULT_PROXYRANDOMIZE));
     strUsage += HelpMessageOpt(
         "-seednode=<ip>",
         _("Connect to a node to retrieve peer addresses, and disconnect"));
     strUsage += HelpMessageOpt(
         "-timeout=<n>", strprintf(_("Specify connection timeout in "
                                     "milliseconds (minimum: 1, default: %d)"),
                                   DEFAULT_CONNECT_TIMEOUT));
     strUsage += HelpMessageOpt("-torcontrol=<ip>:<port>",
                                strprintf(_("Tor control port to use if onion "
                                            "listening enabled (default: %s)"),
                                          DEFAULT_TOR_CONTROL));
     strUsage += HelpMessageOpt("-torpassword=<pass>",
                                _("Tor control port password (default: empty)"));
 #ifdef USE_UPNP
 #if USE_UPNP
     strUsage +=
         HelpMessageOpt("-upnp", _("Use UPnP to map the listening port "
                                   "(default: 1 when listening and no -proxy)"));
 #else
     strUsage += HelpMessageOpt(
         "-upnp",
         strprintf(_("Use UPnP to map the listening port (default: %u)"), 0));
 #endif
 #endif
     strUsage +=
         HelpMessageOpt("-whitebind=<addr>",
                        _("Bind to given address and whitelist peers connecting "
                          "to it. Use [host]:port notation for IPv6"));
     strUsage += HelpMessageOpt(
         "-whitelist=<IP address or network>",
         _("Whitelist peers connecting from the given IP address (e.g. 1.2.3.4) "
           "or CIDR notated network (e.g. 1.2.3.0/24). Can be specified "
           "multiple times.") +
             " " +
             _("Whitelisted peers cannot be DoS banned and their transactions "
               "are always relayed, even if they are already in the mempool, "
               "useful e.g. for a gateway"));
     strUsage += HelpMessageOpt(
         "-whitelistrelay",
         strprintf(_("Accept relayed transactions received from whitelisted "
                     "peers even when not relaying transactions (default: %d)"),
                   DEFAULT_WHITELISTRELAY));
     strUsage += HelpMessageOpt(
         "-whitelistforcerelay",
         strprintf(_("Force relay of transactions from whitelisted peers even "
                     "if they violate local relay policy (default: %d)"),
                   DEFAULT_WHITELISTFORCERELAY));
     strUsage += HelpMessageOpt(
         "-maxuploadtarget=<n>",
         strprintf(_("Tries to keep outbound traffic under the given target (in "
                     "MiB per 24h), 0 = no limit (default: %d)"),
                   DEFAULT_MAX_UPLOAD_TARGET));
 
     strUsage += g_wallet_init_interface->GetHelpString(showDebug);
 
 #if ENABLE_ZMQ
     strUsage += HelpMessageGroup(_("ZeroMQ notification options:"));
     strUsage += HelpMessageOpt("-zmqpubhashblock=<address>",
                                _("Enable publish hash block in <address>"));
     strUsage +=
         HelpMessageOpt("-zmqpubhashtx=<address>",
                        _("Enable publish hash transaction in <address>"));
     strUsage += HelpMessageOpt("-zmqpubrawblock=<address>",
                                _("Enable publish raw block in <address>"));
     strUsage +=
         HelpMessageOpt("-zmqpubrawtx=<address>",
                        _("Enable publish raw transaction in <address>"));
 #endif
 
     strUsage += HelpMessageGroup(_("Debugging/Testing options:"));
     strUsage += HelpMessageOpt("-uacomment=<cmt>",
                                _("Append comment to the user agent string"));
     if (showDebug) {
         strUsage += HelpMessageOpt(
             "-checkblocks=<n>",
             strprintf(
                 _("How many blocks to check at startup (default: %u, 0 = all)"),
                 DEFAULT_CHECKBLOCKS));
         strUsage +=
             HelpMessageOpt("-checklevel=<n>",
                            strprintf(_("How thorough the block verification of "
                                        "-checkblocks is (0-4, default: %u)"),
                                      DEFAULT_CHECKLEVEL));
         strUsage += HelpMessageOpt(
             "-checkblockindex",
             strprintf("Do a full consistency check for mapBlockIndex, "
                       "setBlockIndexCandidates, chainActive and "
                       "mapBlocksUnlinked occasionally. Also sets -checkmempool "
                       "(default: %u)",
                       defaultChainParams->DefaultConsistencyChecks()));
         strUsage += HelpMessageOpt(
             "-checkmempool=<n>",
             strprintf("Run checks every <n> transactions (default: %u)",
                       defaultChainParams->DefaultConsistencyChecks()));
         strUsage += HelpMessageOpt(
             "-checkpoints", strprintf("Only accept block chain matching "
                                       "built-in checkpoints (default: %d)",
                                       DEFAULT_CHECKPOINTS_ENABLED));
         strUsage +=
             HelpMessageOpt("-deprecatedrpc=<method>",
                            "Allows deprecated RPC method(s) to be used");
         strUsage +=
             HelpMessageOpt("-dropmessagestest=<n>",
                            "Randomly drop 1 of every <n> network messages");
         strUsage += HelpMessageOpt(
             "-stopafterblockimport",
             strprintf(
                 "Stop running after importing blocks from disk (default: %d)",
                 DEFAULT_STOPAFTERBLOCKIMPORT));
         strUsage += HelpMessageOpt(
             "-stopatheight", strprintf("Stop running after reaching the given "
                                        "height in the main chain (default: %u)",
                                        DEFAULT_STOPATHEIGHT));
         strUsage += HelpMessageOpt(
             "-limitancestorcount=<n>",
             strprintf("Do not accept transactions if number of in-mempool "
                       "ancestors is <n> or more (default: %u)",
                       DEFAULT_ANCESTOR_LIMIT));
         strUsage +=
             HelpMessageOpt("-limitancestorsize=<n>",
                            strprintf("Do not accept transactions whose size "
                                      "with all in-mempool ancestors exceeds "
                                      "<n> kilobytes (default: %u)",
                                      DEFAULT_ANCESTOR_SIZE_LIMIT));
         strUsage += HelpMessageOpt(
             "-limitdescendantcount=<n>",
             strprintf("Do not accept transactions if any ancestor would have "
                       "<n> or more in-mempool descendants (default: %u)",
                       DEFAULT_DESCENDANT_LIMIT));
         strUsage += HelpMessageOpt(
             "-limitdescendantsize=<n>",
             strprintf("Do not accept transactions if any ancestor would have "
                       "more than <n> kilobytes of in-mempool descendants "
                       "(default: %u).",
                       DEFAULT_DESCENDANT_SIZE_LIMIT));
         strUsage += HelpMessageOpt("-addrmantest",
                                    "Allows to test address relay on localhost");
     }
     strUsage += HelpMessageOpt(
         "-debug=<category>",
         strprintf(_("Output debugging information (default: %u, supplying "
                     "<category> is optional)"),
                   0) +
             ". " +
             _("If <category> is not supplied or if <category> = 1, output all "
               "debugging information.") +
             _("<category> can be:") + " " + ListLogCategories() + ".");
     strUsage += HelpMessageOpt(
         "-debugexclude=<category>",
         strprintf(_("Exclude debugging information for a category. Can be used "
                     "in conjunction with -debug=1 to output debug logs for all "
                     "categories except one or more specified categories.")));
     if (showDebug) {
         strUsage += HelpMessageOpt(
             "-nodebug", "Turn off debugging messages, same as -debug=0");
     }
     strUsage += HelpMessageOpt(
         "-help-debug",
         _("Show all debugging options (usage: --help -help-debug)"));
     strUsage += HelpMessageOpt(
         "-logips",
         strprintf(_("Include IP addresses in debug output (default: %d)"),
                   DEFAULT_LOGIPS));
     strUsage += HelpMessageOpt(
         "-logtimestamps",
         strprintf(_("Prepend debug output with timestamp (default: %d)"),
                   DEFAULT_LOGTIMESTAMPS));
     if (showDebug) {
         strUsage += HelpMessageOpt(
             "-logtimemicros",
             strprintf(
                 "Add microsecond precision to debug timestamps (default: %d)",
                 DEFAULT_LOGTIMEMICROS));
         strUsage += HelpMessageOpt(
             "-mocktime=<n>",
             "Replace actual time with <n> seconds since epoch (default: 0)");
         strUsage += HelpMessageOpt(
             "-limitfreerelay=<n>",
             strprintf("Continuously rate-limit free transactions to <n>*1000 "
                       "bytes per minute (default: %u)",
                       DEFAULT_LIMITFREERELAY));
         strUsage +=
             HelpMessageOpt("-relaypriority",
                            strprintf("Require high priority for relaying free "
                                      "or low-fee transactions (default: %d)",
                                      DEFAULT_RELAYPRIORITY));
         strUsage += HelpMessageOpt(
             "-maxsigcachesize=<n>",
             strprintf("Limit size of signature cache to <n> MiB (default: %u)",
                       DEFAULT_MAX_SIG_CACHE_SIZE));
         strUsage += HelpMessageOpt(
             "-maxscriptcachesize=<n>",
             strprintf("Limit size of script cache to <n> MiB (default: %u)",
                       DEFAULT_MAX_SCRIPT_CACHE_SIZE));
         strUsage += HelpMessageOpt(
             "-maxtipage=<n>",
             strprintf("Maximum tip age in seconds to consider node in initial "
                       "block download (default: %u)",
                       DEFAULT_MAX_TIP_AGE));
     }
     strUsage += HelpMessageOpt(
         "-excessutxocharge=<amt>",
         strprintf(_("Fees (in %s/kB) to charge per utxo created for"
                     "relaying, and mining (default: %s)"),
                   CURRENCY_UNIT, FormatMoney(DEFAULT_UTXO_FEE)));
     strUsage += HelpMessageOpt(
         "-minrelaytxfee=<amt>",
         strprintf(
             _("Fees (in %s/kB) smaller than this are considered zero fee for "
               "relaying, mining and transaction creation (default: %s)"),
             CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE_PER_KB)));
     strUsage += HelpMessageOpt(
         "-maxtxfee=<amt>",
         strprintf(_("Maximum total fees (in %s) to use in a single wallet "
                     "transaction or raw transaction; setting this too low may "
                     "abort large transactions (default: %s)"),
                   CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MAXFEE)));
     strUsage += HelpMessageOpt(
         "-printtoconsole",
         _("Send trace/debug info to console instead of debug.log file"));
     if (showDebug) {
         strUsage += HelpMessageOpt(
             "-printpriority", strprintf("Log transaction priority and fee per "
                                         "kB when mining blocks (default: %d)",
                                         DEFAULT_PRINTPRIORITY));
     }
     strUsage += HelpMessageOpt("-shrinkdebugfile",
                                _("Shrink debug.log file on client startup "
                                  "(default: 1 when no -debug)"));
 
     AppendParamsHelpMessages(strUsage, showDebug);
 
     strUsage += HelpMessageGroup(_("Node relay options:"));
     if (showDebug) {
         strUsage += HelpMessageOpt(
             "-acceptnonstdtxn",
             strprintf(
                 "Relay and mine \"non-standard\" transactions (%sdefault: %u)",
                 "testnet/regtest only; ",
                 defaultChainParams->RequireStandard()));
         strUsage +=
             HelpMessageOpt("-excessiveblocksize=<n>",
                            strprintf(_("Do not accept blocks larger than this "
                                        "limit, in bytes (default: %d)"),
                                      DEFAULT_MAX_BLOCK_SIZE));
         strUsage += HelpMessageOpt(
             "-dustrelayfee=<amt>",
             strprintf("Fee rate (in %s/kB) used to defined dust, the value of "
                       "an output such that it will cost about 1/3 of its value "
                       "in fees at this fee rate to spend it. (default: %s)",
                       CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)));
     }
     strUsage +=
         HelpMessageOpt("-bytespersigop",
                        strprintf(_("Equivalent bytes per sigop in transactions "
                                    "for relay and mining (default: %u)"),
                                  DEFAULT_BYTES_PER_SIGOP));
     strUsage += HelpMessageOpt(
         "-datacarrier",
         strprintf(_("Relay and mine data carrier transactions (default: %d)"),
                   DEFAULT_ACCEPT_DATACARRIER));
     strUsage += HelpMessageOpt(
         "-datacarriersize",
         strprintf(_("Maximum size of data in data carrier transactions we "
                     "relay and mine (default: %u)"),
                   MAX_OP_RETURN_RELAY));
 
     strUsage += HelpMessageGroup(_("Block creation options:"));
     strUsage += HelpMessageOpt(
         "-blockmaxsize=<n>",
         strprintf(_("Set maximum block size in bytes (default: %d)"),
                   DEFAULT_MAX_GENERATED_BLOCK_SIZE));
     strUsage += HelpMessageOpt(
         "-blockprioritypercentage=<n>",
         strprintf(_("Set maximum percentage of a block reserved to "
                     "high-priority/low-fee transactions (default: %d)"),
                   DEFAULT_BLOCK_PRIORITY_PERCENTAGE));
     strUsage += HelpMessageOpt(
         "-blockmintxfee=<amt>",
         strprintf(_("Set lowest fee rate (in %s/kB) for transactions to be "
                     "included in block creation. (default: %s)"),
                   CURRENCY_UNIT, FormatMoney(DEFAULT_BLOCK_MIN_TX_FEE_PER_KB)));
     if (showDebug) {
         strUsage +=
             HelpMessageOpt("-blockversion=<n>",
                            "Override block version to test forking scenarios");
     }
 
     strUsage += HelpMessageGroup(_("RPC server options:"));
     strUsage += HelpMessageOpt("-server",
                                _("Accept command line and JSON-RPC commands"));
     strUsage += HelpMessageOpt(
         "-rest", strprintf(_("Accept public REST requests (default: %d)"),
                            DEFAULT_REST_ENABLE));
     strUsage += HelpMessageOpt(
         "-rpcbind=<addr>",
         _("Bind to given address to listen for JSON-RPC connections. Use "
           "[host]:port notation for IPv6. This option can be specified "
           "multiple times (default: bind to all interfaces)"));
     strUsage +=
         HelpMessageOpt("-rpccookiefile=<loc>",
                        _("Location of the auth cookie (default: data dir)"));
     strUsage += HelpMessageOpt("-rpcuser=<user>",
                                _("Username for JSON-RPC connections"));
     strUsage += HelpMessageOpt("-rpcpassword=<pw>",
                                _("Password for JSON-RPC connections"));
     strUsage += HelpMessageOpt(
         "-rpcauth=<userpw>",
         _("Username and hashed password for JSON-RPC connections. The field "
           "<userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical "
           "python script is included in share/rpcuser. The client then "
           "connects normally using the "
           "rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This "
           "option can be specified multiple times"));
     strUsage += HelpMessageOpt(
         "-rpcport=<port>",
         strprintf(_("Listen for JSON-RPC connections on <port> (default: %u or "
                     "testnet: %u)"),
                   defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort()));
     strUsage += HelpMessageOpt(
         "-rpcallowip=<ip>",
         _("Allow JSON-RPC connections from specified source. Valid for <ip> "
           "are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. "
           "1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This "
           "option can be specified multiple times"));
     strUsage += HelpMessageOpt(
         "-rpcthreads=<n>",
         strprintf(
             _("Set the number of threads to service RPC calls (default: %d)"),
             DEFAULT_HTTP_THREADS));
     strUsage += HelpMessageOpt(
         "-rpccorsdomain=value",
         "Domain from which to accept cross origin requests (browser enforced)");
     if (showDebug) {
         strUsage += HelpMessageOpt(
             "-rpcworkqueue=<n>", strprintf("Set the depth of the work queue to "
                                            "service RPC calls (default: %d)",
                                            DEFAULT_HTTP_WORKQUEUE));
         strUsage += HelpMessageOpt(
             "-rpcservertimeout=<n>",
             strprintf("Timeout during HTTP requests (default: %d)",
                       DEFAULT_HTTP_SERVER_TIMEOUT));
     }
 
     return strUsage;
 }
 
 std::string LicenseInfo() {
     const std::string URL_SOURCE_CODE =
         "<https://github.com/Bitcoin-ABC/bitcoin-abc>";
     const std::string URL_WEBSITE = "<https://www.bitcoinabc.org>";
 
     return CopyrightHolders(
                strprintf(_("Copyright (C) %i-%i"), 2009, COPYRIGHT_YEAR) +
                " ") +
            "\n" + "\n" +
            strprintf(_("Please contribute if you find %s useful. "
                        "Visit %s for further information about the software."),
                      PACKAGE_NAME, URL_WEBSITE) +
            "\n" +
            strprintf(_("The source code is available from %s."),
                      URL_SOURCE_CODE) +
            "\n" + "\n" + _("This is experimental software.") + "\n" +
            strprintf(_("Distributed under the MIT software license, see the "
                        "accompanying file %s or %s"),
                      "COPYING", "<https://opensource.org/licenses/MIT>") +
            "\n" + "\n" +
            strprintf(_("This product includes software developed by the "
                        "OpenSSL Project for use in the OpenSSL Toolkit %s and "
                        "cryptographic software written by Eric Young and UPnP "
                        "software written by Thomas Bernard."),
                      "<https://www.openssl.org>") +
            "\n";
 }
 
 static void BlockNotifyCallback(bool initialSync,
                                 const CBlockIndex *pBlockIndex) {
     if (initialSync || !pBlockIndex) {
         return;
     }
 
     std::string strCmd = gArgs.GetArg("-blocknotify", "");
     if (!strCmd.empty()) {
         boost::replace_all(strCmd, "%s", pBlockIndex->GetBlockHash().GetHex());
         std::thread t(runCommand, strCmd);
         // thread runs free
         t.detach();
     }
 }
 
 static bool fHaveGenesis = false;
 static CWaitableCriticalSection cs_GenesisWait;
 static CConditionVariable condvar_GenesisWait;
 
 static void BlockNotifyGenesisWait(bool, const CBlockIndex *pBlockIndex) {
     if (pBlockIndex != nullptr) {
         {
             LOCK(cs_GenesisWait);
             fHaveGenesis = true;
         }
         condvar_GenesisWait.notify_all();
     }
 }
 
 struct CImportingNow {
     CImportingNow() {
         assert(fImporting == false);
         fImporting = true;
     }
 
     ~CImportingNow() {
         assert(fImporting == true);
         fImporting = false;
     }
 };
 
 // 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
 // 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
 // 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
 // pruning works correctly.
 void CleanupBlockRevFiles() {
     std::map<std::string, fs::path> mapBlockFiles;
 
     // 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
     // ordered map keyed by block file index.
     LogPrintf("Removing unusable blk?????.dat and rev?????.dat files for "
               "-reindex with -prune\n");
     fs::path blocksdir = GetDataDir() / "blocks";
     for (fs::directory_iterator it(blocksdir); it != fs::directory_iterator();
          it++) {
         if (is_regular_file(*it) &&
             it->path().filename().string().length() == 12 &&
             it->path().filename().string().substr(8, 4) == ".dat") {
             if (it->path().filename().string().substr(0, 3) == "blk") {
                 mapBlockFiles[it->path().filename().string().substr(3, 5)] =
                     it->path();
             } else if (it->path().filename().string().substr(0, 3) == "rev") {
                 remove(it->path());
             }
         }
     }
 
     // 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
     // a separate counter. Once we hit a gap (or if 0 doesn't exist) start
     // removing block files.
     int nContigCounter = 0;
     for (const std::pair<std::string, fs::path> &item : mapBlockFiles) {
         if (atoi(item.first) == nContigCounter) {
             nContigCounter++;
             continue;
         }
         remove(item.second);
     }
 }
 
 void ThreadImport(const Config &config, std::vector<fs::path> vImportFiles) {
     RenameThread("bitcoin-loadblk");
 
     {
         CImportingNow imp;
 
         // -reindex
         if (fReindex) {
             int nFile = 0;
             while (true) {
                 CDiskBlockPos pos(nFile, 0);
                 if (!fs::exists(GetBlockPosFilename(pos, "blk"))) {
                     // No block files left to reindex
                     break;
                 }
                 FILE *file = OpenBlockFile(pos, true);
                 if (!file) {
                     // This error is logged in OpenBlockFile
                     break;
                 }
                 LogPrintf("Reindexing block file blk%05u.dat...\n",
                           (unsigned int)nFile);
                 LoadExternalBlockFile(config, file, &pos);
                 nFile++;
             }
             pblocktree->WriteReindexing(false);
             fReindex = false;
             LogPrintf("Reindexing finished\n");
             // To avoid ending up in a situation without genesis block, re-try
             // initializing (no-op if reindexing worked):
             LoadGenesisBlock(config.GetChainParams());
         }
 
         // hardcoded $DATADIR/bootstrap.dat
         fs::path pathBootstrap = GetDataDir() / "bootstrap.dat";
         if (fs::exists(pathBootstrap)) {
             FILE *file = fsbridge::fopen(pathBootstrap, "rb");
             if (file) {
                 fs::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old";
                 LogPrintf("Importing bootstrap.dat...\n");
                 LoadExternalBlockFile(config, file);
                 RenameOver(pathBootstrap, pathBootstrapOld);
             } else {
                 LogPrintf("Warning: Could not open bootstrap file %s\n",
                           pathBootstrap.string());
             }
         }
 
         // -loadblock=
         for (const fs::path &path : vImportFiles) {
             FILE *file = fsbridge::fopen(path, "rb");
             if (file) {
                 LogPrintf("Importing blocks file %s...\n", path.string());
                 LoadExternalBlockFile(config, file);
             } else {
                 LogPrintf("Warning: Could not open blocks file %s\n",
                           path.string());
             }
         }
 
         // scan for better chains in the block chain database, that are not yet
         // connected in the active best chain
         CValidationState state;
         if (!ActivateBestChain(config, state)) {
             LogPrintf("Failed to connect best block");
             StartShutdown();
         }
 
         if (gArgs.GetBoolArg("-stopafterblockimport",
                              DEFAULT_STOPAFTERBLOCKIMPORT)) {
             LogPrintf("Stopping after block import\n");
             StartShutdown();
         }
     } // End scope of CImportingNow
     if (gArgs.GetArg("-persistmempool", DEFAULT_PERSIST_MEMPOOL)) {
         LoadMempool(config);
         fDumpMempoolLater = !fRequestShutdown;
     }
 }
 
 /** Sanity checks
  *  Ensure that Bitcoin is running in a usable environment with all
  *  necessary library support.
  */
 bool InitSanityCheck(void) {
     if (!ECC_InitSanityCheck()) {
         InitError(
             "Elliptic curve cryptography sanity check failure. Aborting.");
         return false;
     }
 
     if (!glibc_sanity_test() || !glibcxx_sanity_test()) {
         return false;
     }
 
     if (!Random_SanityCheck()) {
         InitError("OS cryptographic RNG sanity check failure. Aborting.");
         return false;
     }
 
     return true;
 }
 
 static bool AppInitServers(Config &config,
                            HTTPRPCRequestProcessor &httpRPCRequestProcessor) {
     RPCServerSignals::OnStarted(&OnRPCStarted);
     RPCServerSignals::OnStopped(&OnRPCStopped);
     if (!InitHTTPServer(config)) {
         return false;
     }
     if (!StartRPC()) {
         return false;
     }
     if (!StartHTTPRPC(config, httpRPCRequestProcessor)) {
         return false;
     }
     if (gArgs.GetBoolArg("-rest", DEFAULT_REST_ENABLE) && !StartREST()) {
         return false;
     }
     if (!StartHTTPServer()) {
         return false;
     }
     return true;
 }
 
 // Parameter interaction based on rules
 void InitParameterInteraction() {
     // when specifying an explicit binding address, you want to listen on it
     // even when -connect or -proxy is specified.
     if (gArgs.IsArgSet("-bind")) {
         if (gArgs.SoftSetBoolArg("-listen", true)) {
             LogPrintf(
                 "%s: parameter interaction: -bind set -> setting -listen=1\n",
                 __func__);
         }
     }
     if (gArgs.IsArgSet("-whitebind")) {
         if (gArgs.SoftSetBoolArg("-listen", true)) {
             LogPrintf("%s: parameter interaction: -whitebind set -> setting "
                       "-listen=1\n",
                       __func__);
         }
     }
 
     if (gArgs.IsArgSet("-connect")) {
         // when only connecting to trusted nodes, do not seed via DNS, or listen
         // by default.
         if (gArgs.SoftSetBoolArg("-dnsseed", false)) {
             LogPrintf("%s: parameter interaction: -connect set -> setting "
                       "-dnsseed=0\n",
                       __func__);
         }
         if (gArgs.SoftSetBoolArg("-listen", false)) {
             LogPrintf("%s: parameter interaction: -connect set -> setting "
                       "-listen=0\n",
                       __func__);
         }
     }
 
     if (gArgs.IsArgSet("-proxy")) {
         // to protect privacy, do not listen by default if a default proxy
         // server is specified.
         if (gArgs.SoftSetBoolArg("-listen", false)) {
             LogPrintf(
                 "%s: parameter interaction: -proxy set -> setting -listen=0\n",
                 __func__);
         }
         // to protect privacy, do not use UPNP when a proxy is set. The user may
         // still specify -listen=1 to listen locally, so don't rely on this
         // happening through -listen below.
         if (gArgs.SoftSetBoolArg("-upnp", false)) {
             LogPrintf(
                 "%s: parameter interaction: -proxy set -> setting -upnp=0\n",
                 __func__);
         }
         // to protect privacy, do not discover addresses by default
         if (gArgs.SoftSetBoolArg("-discover", false)) {
             LogPrintf("%s: parameter interaction: -proxy set -> setting "
                       "-discover=0\n",
                       __func__);
         }
     }
 
     if (!gArgs.GetBoolArg("-listen", DEFAULT_LISTEN)) {
         // do not map ports or try to retrieve public IP when not listening
         // (pointless)
         if (gArgs.SoftSetBoolArg("-upnp", false)) {
             LogPrintf(
                 "%s: parameter interaction: -listen=0 -> setting -upnp=0\n",
                 __func__);
         }
         if (gArgs.SoftSetBoolArg("-discover", false)) {
             LogPrintf(
                 "%s: parameter interaction: -listen=0 -> setting -discover=0\n",
                 __func__);
         }
         if (gArgs.SoftSetBoolArg("-listenonion", false)) {
             LogPrintf("%s: parameter interaction: -listen=0 -> setting "
                       "-listenonion=0\n",
                       __func__);
         }
     }
 
     if (gArgs.IsArgSet("-externalip")) {
         // if an explicit public IP is specified, do not try to find others
         if (gArgs.SoftSetBoolArg("-discover", false)) {
             LogPrintf("%s: parameter interaction: -externalip set -> setting "
                       "-discover=0\n",
                       __func__);
         }
     }
 
     // disable whitelistrelay in blocksonly mode
     if (gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)) {
         if (gArgs.SoftSetBoolArg("-whitelistrelay", false)) {
             LogPrintf("%s: parameter interaction: -blocksonly=1 -> setting "
                       "-whitelistrelay=0\n",
                       __func__);
         }
     }
 
     // Forcing relay from whitelisted hosts implies we will accept relays from
     // them in the first place.
     if (gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) {
         if (gArgs.SoftSetBoolArg("-whitelistrelay", true)) {
             LogPrintf("%s: parameter interaction: -whitelistforcerelay=1 -> "
                       "setting -whitelistrelay=1\n",
                       __func__);
         }
     }
 
     // Warn if network-specific options (-addnode, -connect, etc) are
     // specified in default section of config file, but not overridden
     // on the command line or in this network's section of the config file.
     gArgs.WarnForSectionOnlyArgs();
 }
 
 static std::string ResolveErrMsg(const char *const optname,
                                  const std::string &strBind) {
     return strprintf(_("Cannot resolve -%s address: '%s'"), optname, strBind);
 }
 
 void InitLogging() {
     BCLog::Logger &logger = GetLogger();
     logger.m_print_to_console = gArgs.GetBoolArg("-printtoconsole", false);
     logger.m_log_timestamps =
         gArgs.GetBoolArg("-logtimestamps", DEFAULT_LOGTIMESTAMPS);
     logger.m_log_time_micros =
         gArgs.GetBoolArg("-logtimemicros", DEFAULT_LOGTIMEMICROS);
 
     fLogIPs = gArgs.GetBoolArg("-logips", DEFAULT_LOGIPS);
 
     LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
     LogPrintf("%s version %s\n", CLIENT_NAME, FormatFullVersion());
 }
 
 namespace { // Variables internal to initialization process only
 
 int nMaxConnections;
 int nUserMaxConnections;
 int nFD;
 ServiceFlags nLocalServices = ServiceFlags(NODE_NETWORK | NODE_NETWORK_LIMITED);
 } // namespace
 
 [[noreturn]] static void new_handler_terminate() {
     // Rather than throwing std::bad-alloc if allocation fails, terminate
     // immediately to (try to) avoid chain corruption. Since LogPrintf may
     // itself allocate memory, set the handler directly to terminate first.
     std::set_new_handler(std::terminate);
     LogPrintf("Error: Out of memory. Terminating.\n");
 
     // The log was successful, terminate now.
     std::terminate();
 };
 
 bool AppInitBasicSetup() {
 // Step 1: setup
 #ifdef _MSC_VER
     // Turn off Microsoft heap dump noise
     _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
     _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, nullptr,
                                              OPEN_EXISTING, 0, 0));
 #endif
 #if _MSC_VER >= 1400
     // Disable confusing "helpful" text message on abort, Ctrl-C
     _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
 #endif
 #ifdef WIN32
 // Enable Data Execution Prevention (DEP)
 // Minimum supported OS versions: WinXP SP3, WinVista >= SP1, Win Server 2008
 // A failure is non-critical and needs no further attention!
 #ifndef PROCESS_DEP_ENABLE
 // We define this here, because GCCs winbase.h limits this to _WIN32_WINNT >=
 // 0x0601 (Windows 7), which is not correct. Can be removed, when GCCs winbase.h
 // is fixed!
 #define PROCESS_DEP_ENABLE 0x00000001
 #endif
     typedef BOOL(WINAPI * PSETPROCDEPPOL)(DWORD);
     PSETPROCDEPPOL setProcDEPPol = (PSETPROCDEPPOL)GetProcAddress(
         GetModuleHandleA("Kernel32.dll"), "SetProcessDEPPolicy");
     if (setProcDEPPol != nullptr) {
         setProcDEPPol(PROCESS_DEP_ENABLE);
     }
 #endif
 
     if (!SetupNetworking()) {
         return InitError("Initializing networking failed");
     }
 
 #ifndef WIN32
     if (!gArgs.GetBoolArg("-sysperms", false)) {
         umask(077);
     }
 
     // Clean shutdown on SIGTERM
     struct sigaction sa;
     sa.sa_handler = HandleSIGTERM;
     sigemptyset(&sa.sa_mask);
     sa.sa_flags = 0;
     sigaction(SIGTERM, &sa, nullptr);
     sigaction(SIGINT, &sa, nullptr);
 
     // Reopen debug.log on SIGHUP
     struct sigaction sa_hup;
     sa_hup.sa_handler = HandleSIGHUP;
     sigemptyset(&sa_hup.sa_mask);
     sa_hup.sa_flags = 0;
     sigaction(SIGHUP, &sa_hup, nullptr);
 
     // Ignore SIGPIPE, otherwise it will bring the daemon down if the client
     // closes unexpectedly
     signal(SIGPIPE, SIG_IGN);
 #endif
 
     std::set_new_handler(new_handler_terminate);
 
     return true;
 }
 
 bool AppInitParameterInteraction(Config &config, RPCServer &rpcServer) {
     const CChainParams &chainparams = config.GetChainParams();
     // Step 2: parameter interactions
 
     // also see: InitParameterInteraction()
 
     // if using block pruning, then disallow txindex
     if (gArgs.GetArg("-prune", 0)) {
         if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
             return InitError(_("Prune mode is incompatible with -txindex."));
         }
     }
 
     // if space reserved for high priority transactions is misconfigured
     // stop program execution and warn the user with a proper error message
     const int64_t blkprio = gArgs.GetArg("-blockprioritypercentage",
                                          DEFAULT_BLOCK_PRIORITY_PERCENTAGE);
     if (!config.SetBlockPriorityPercentage(blkprio)) {
         return InitError(_("Block priority percentage has to belong to the "
                            "[0..100] interval."));
     }
 
     // -bind and -whitebind can't be set when not listening
     size_t nUserBind =
         gArgs.GetArgs("-bind").size() + gArgs.GetArgs("-whitebind").size();
     if (nUserBind != 0 && !gArgs.GetBoolArg("-listen", DEFAULT_LISTEN)) {
         return InitError(
             "Cannot set -bind or -whitebind together with -listen=0");
     }
 
     // Make sure enough file descriptors are available
     int nBind = std::max(nUserBind, size_t(1));
     nUserMaxConnections =
         gArgs.GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS);
     nMaxConnections = std::max(nUserMaxConnections, 0);
 
     // Trim requested connection counts, to fit into system limitations
     nMaxConnections =
         std::max(std::min(nMaxConnections,
                           (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS -
                                 MAX_ADDNODE_CONNECTIONS)),
                  0);
     nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS +
                                    MAX_ADDNODE_CONNECTIONS);
     if (nFD < MIN_CORE_FILEDESCRIPTORS) {
         return InitError(_("Not enough file descriptors available."));
     }
     nMaxConnections =
         std::min(nFD - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS,
                  nMaxConnections);
 
     if (nMaxConnections < nUserMaxConnections) {
         InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, "
                                 "because of system limitations."),
                               nUserMaxConnections, nMaxConnections));
     }
 
     // Step 3: parameter-to-internal-flags
     if (gArgs.IsArgSet("-debug")) {
         // Special-case: if -debug=0/-nodebug is set, turn off debugging
         // messages
         const std::vector<std::string> &categories = gArgs.GetArgs("-debug");
         if (find(categories.begin(), categories.end(), std::string("0")) ==
             categories.end()) {
             for (const auto &cat : categories) {
                 BCLog::LogFlags flag;
                 if (!GetLogCategory(flag, cat)) {
                     InitWarning(
                         strprintf(_("Unsupported logging category %s=%s."),
                                   "-debug", cat));
                 }
                 GetLogger().EnableCategory(flag);
             }
         }
     }
 
     // Now remove the logging categories which were explicitly excluded
     for (const std::string &cat : gArgs.GetArgs("-debugexclude")) {
         BCLog::LogFlags flag;
         if (!GetLogCategory(flag, cat)) {
             InitWarning(strprintf(_("Unsupported logging category %s=%s."),
                                   "-debugexclude", cat));
         }
         GetLogger().DisableCategory(flag);
     }
 
     // Check for -debugnet
     if (gArgs.GetBoolArg("-debugnet", false)) {
         InitWarning(
             _("Unsupported argument -debugnet ignored, use -debug=net."));
     }
     // Check for -socks - as this is a privacy risk to continue, exit here
     if (gArgs.IsArgSet("-socks")) {
         return InitError(
             _("Unsupported argument -socks found. Setting SOCKS version isn't "
               "possible anymore, only SOCKS5 proxies are supported."));
     }
     // Check for -tor - as this is a privacy risk to continue, exit here
     if (gArgs.GetBoolArg("-tor", false)) {
         return InitError(_("Unsupported argument -tor found, use -onion."));
     }
 
     if (gArgs.GetBoolArg("-benchmark", false)) {
         InitWarning(
             _("Unsupported argument -benchmark ignored, use -debug=bench."));
     }
 
     if (gArgs.GetBoolArg("-whitelistalwaysrelay", false)) {
         InitWarning(_("Unsupported argument -whitelistalwaysrelay ignored, use "
                       "-whitelistrelay and/or -whitelistforcerelay."));
     }
 
     if (gArgs.IsArgSet("-blockminsize")) {
         InitWarning("Unsupported argument -blockminsize ignored.");
     }
 
     // Checkmempool and checkblockindex default to true in regtest mode
     int ratio = std::min<int>(
         std::max<int>(
             gArgs.GetArg("-checkmempool",
                          chainparams.DefaultConsistencyChecks() ? 1 : 0),
             0),
         1000000);
     if (ratio != 0) {
         g_mempool.setSanityCheck(1.0 / ratio);
     }
     fCheckBlockIndex = gArgs.GetBoolArg("-checkblockindex",
                                         chainparams.DefaultConsistencyChecks());
     fCheckpointsEnabled =
         gArgs.GetBoolArg("-checkpoints", DEFAULT_CHECKPOINTS_ENABLED);
     if (fCheckpointsEnabled) {
         LogPrintf("Checkpoints will be verified.\n");
     } else {
         LogPrintf("Skipping checkpoint verification.\n");
     }
 
     hashAssumeValid = uint256S(
         gArgs.GetArg("-assumevalid",
                      chainparams.GetConsensus().defaultAssumeValid.GetHex()));
     if (!hashAssumeValid.IsNull()) {
         LogPrintf("Assuming ancestors of block %s have valid signatures.\n",
                   hashAssumeValid.GetHex());
     } else {
         LogPrintf("Validating signatures for all blocks.\n");
     }
 
     if (gArgs.IsArgSet("-minimumchainwork")) {
         const std::string minChainWorkStr =
             gArgs.GetArg("-minimumchainwork", "");
         if (!IsHexNumber(minChainWorkStr)) {
             return InitError(strprintf(
                 "Invalid non-hex (%s) minimum chain work value specified",
                 minChainWorkStr));
         }
         nMinimumChainWork = UintToArith256(uint256S(minChainWorkStr));
     } else {
         nMinimumChainWork =
             UintToArith256(chainparams.GetConsensus().nMinimumChainWork);
     }
     LogPrintf("Setting nMinimumChainWork=%s\n", nMinimumChainWork.GetHex());
     if (nMinimumChainWork <
         UintToArith256(chainparams.GetConsensus().nMinimumChainWork)) {
         LogPrintf("Warning: nMinimumChainWork set below default value of %s\n",
                   chainparams.GetConsensus().nMinimumChainWork.GetHex());
     }
 
     // mempool limits
     int64_t nMempoolSizeMax =
         gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
     int64_t nMempoolSizeMin =
         gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) *
         1000 * 40;
     if (nMempoolSizeMax < 0 || nMempoolSizeMax < nMempoolSizeMin) {
         return InitError(strprintf(_("-maxmempool must be at least %d MB"),
                                    std::ceil(nMempoolSizeMin / 1000000.0)));
     }
 
     // -par=0 means autodetect, but nScriptCheckThreads==0 means no concurrency
     nScriptCheckThreads = gArgs.GetArg("-par", DEFAULT_SCRIPTCHECK_THREADS);
     if (nScriptCheckThreads <= 0) {
         nScriptCheckThreads += GetNumCores();
     }
     if (nScriptCheckThreads <= 1) {
         nScriptCheckThreads = 0;
     } else if (nScriptCheckThreads > MAX_SCRIPTCHECK_THREADS) {
         nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS;
     }
 
     // Configure excessive block size.
     const uint64_t nProposedExcessiveBlockSize =
         gArgs.GetArg("-excessiveblocksize", DEFAULT_MAX_BLOCK_SIZE);
     if (!config.SetMaxBlockSize(nProposedExcessiveBlockSize)) {
         return InitError(
             _("Excessive block size must be > 1,000,000 bytes (1MB)"));
     }
 
     // Check blockmaxsize does not exceed maximum accepted block size.
     const uint64_t nProposedMaxGeneratedBlockSize =
         gArgs.GetArg("-blockmaxsize", DEFAULT_MAX_GENERATED_BLOCK_SIZE);
     if (nProposedMaxGeneratedBlockSize > config.GetMaxBlockSize()) {
         auto msg = _("Max generated block size (blockmaxsize) cannot exceed "
                      "the excessive block size (excessiveblocksize)");
         return InitError(msg);
     }
 
     // block pruning; get the amount of disk space (in MiB) to allot for block &
     // undo files
     int64_t nPruneArg = gArgs.GetArg("-prune", 0);
     if (nPruneArg < 0) {
         return InitError(
             _("Prune cannot be configured with a negative value."));
     }
     nPruneTarget = (uint64_t)nPruneArg * 1024 * 1024;
     if (nPruneArg == 1) {
         // manual pruning: -prune=1
         LogPrintf("Block pruning enabled.  Use RPC call "
                   "pruneblockchain(height) to manually prune block and undo "
                   "files.\n");
         nPruneTarget = std::numeric_limits<uint64_t>::max();
         fPruneMode = true;
     } else if (nPruneTarget) {
         if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) {
             return InitError(
                 strprintf(_("Prune configured below the minimum of %d MiB.  "
                             "Please use a higher number."),
                           MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024));
         }
         LogPrintf("Prune configured to target %uMiB on disk for block and undo "
                   "files.\n",
                   nPruneTarget / 1024 / 1024);
         fPruneMode = true;
     }
 
     RegisterAllRPCCommands(config, rpcServer, tableRPC);
     g_wallet_init_interface->RegisterRPC(tableRPC);
 #ifdef ENABLE_WALLET
     RegisterDumpRPCCommands(tableRPC);
 #endif
 
     nConnectTimeout = gArgs.GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT);
     if (nConnectTimeout <= 0) {
         nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
     }
 
     // Obtain the amount to charge excess UTXO
     if (gArgs.IsArgSet("-excessutxocharge")) {
         Amount n = Amount::zero();
         auto parsed = ParseMoney(gArgs.GetArg("-excessutxocharge", ""), n);
         if (!parsed || Amount::zero() > n) {
             return InitError(AmountErrMsg(
                 "excessutxocharge", gArgs.GetArg("-excessutxocharge", "")));
         }
         config.SetExcessUTXOCharge(n);
     } else {
         config.SetExcessUTXOCharge(DEFAULT_UTXO_FEE);
     }
 
     // Fee-per-kilobyte amount considered the same as "free". If you are mining,
     // be careful setting this: if you set it to zero then a transaction spammer
     // can cheaply fill blocks using 1-satoshi-fee transactions. It should be
     // set above the real cost to you of processing a transaction.
     if (gArgs.IsArgSet("-minrelaytxfee")) {
         Amount n = Amount::zero();
         auto parsed = ParseMoney(gArgs.GetArg("-minrelaytxfee", ""), n);
         if (!parsed || Amount::zero() == n) {
             return InitError(AmountErrMsg("minrelaytxfee",
                                           gArgs.GetArg("-minrelaytxfee", "")));
         }
         // High fee check is done afterward in WalletParameterInteraction()
         config.SetMinFeePerKB(CFeeRate(n));
     } else {
         config.SetMinFeePerKB(CFeeRate(DEFAULT_MIN_RELAY_TX_FEE_PER_KB));
     }
 
     // Sanity check argument for min fee for including tx in block
     // TODO: Harmonize which arguments need sanity checking and where that
     // happens.
     if (gArgs.IsArgSet("-blockmintxfee")) {
         Amount n = Amount::zero();
         if (!ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n)) {
             return InitError(AmountErrMsg("blockmintxfee",
                                           gArgs.GetArg("-blockmintxfee", "")));
         }
     }
 
     // Feerate used to define dust.  Shouldn't be changed lightly as old
     // implementations may inadvertently create non-standard transactions.
     if (gArgs.IsArgSet("-dustrelayfee")) {
         Amount n = Amount::zero();
         auto parsed = ParseMoney(gArgs.GetArg("-dustrelayfee", ""), n);
         if (!parsed || Amount::zero() == n) {
             return InitError(AmountErrMsg("dustrelayfee",
                                           gArgs.GetArg("-dustrelayfee", "")));
         }
         dustRelayFee = CFeeRate(n);
     }
 
     fRequireStandard =
         !gArgs.GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard());
     if (chainparams.RequireStandard() && !fRequireStandard) {
         return InitError(
             strprintf("acceptnonstdtxn is not currently supported for %s chain",
                       chainparams.NetworkIDString()));
     }
     nBytesPerSigOp = gArgs.GetArg("-bytespersigop", nBytesPerSigOp);
 
     if (!g_wallet_init_interface->ParameterInteraction()) {
         return false;
     }
 
     fIsBareMultisigStd =
         gArgs.GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG);
     fAcceptDatacarrier =
         gArgs.GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER);
 
     // Option to startup with mocktime set (used for regression testing):
     SetMockTime(gArgs.GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op
 
     if (gArgs.GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS)) {
         nLocalServices = ServiceFlags(nLocalServices | NODE_BLOOM);
     }
 
     // Signal Bitcoin Cash support.
     // TODO: remove some time after the hardfork when no longer needed
     // to differentiate the network nodes.
     nLocalServices = ServiceFlags(nLocalServices | NODE_BITCOIN_CASH);
 
     nMaxTipAge = gArgs.GetArg("-maxtipage", DEFAULT_MAX_TIP_AGE);
 
     return true;
 }
 
 static bool LockDataDirectory(bool probeOnly) {
     // Make sure only a single Bitcoin process is using the data directory.
     fs::path datadir = GetDataDir();
     if (!DirIsWritable(datadir)) {
         return InitError(strprintf(
             _("Cannot write to data directory '%s'; check permissions."),
             datadir.string()));
     }
     if (!LockDirectory(datadir, ".lock", probeOnly)) {
         return InitError(strprintf(_("Cannot obtain a lock on data directory "
                                      "%s. %s is probably already running."),
                                    datadir.string(), _(PACKAGE_NAME)));
     }
     return true;
 }
 
 bool AppInitSanityChecks() {
     // Step 4: sanity checks
 
     // Initialize elliptic curve code
     std::string sha256_algo = SHA256AutoDetect();
     LogPrintf("Using the '%s' SHA256 implementation\n", sha256_algo);
     RandomInit();
     ECC_Start();
     globalVerifyHandle.reset(new ECCVerifyHandle());
 
     // Sanity check
     if (!InitSanityCheck()) {
         return InitError(strprintf(
             _("Initialization sanity check failed. %s is shutting down."),
             _(PACKAGE_NAME)));
     }
 
     // Probe the data directory lock to give an early error message, if possible
     // We cannot hold the data directory lock here, as the forking for daemon()
     // hasn't yet happened, and a fork will cause weird behavior to it.
     return LockDataDirectory(true);
 }
 
 bool AppInitLockDataDirectory() {
     // After daemonization get the data directory lock again and hold on to it
     // until exit. This creates a slight window for a race condition to happen,
     // however this condition is harmless: it will at most make us exit without
     // printing a message to console.
     if (!LockDataDirectory(false)) {
         // Detailed error printed inside LockDataDirectory
         return false;
     }
     return true;
 }
 
 bool AppInitMain(Config &config,
                  HTTPRPCRequestProcessor &httpRPCRequestProcessor) {
     // Step 4a: application initialization
     const CChainParams &chainparams = config.GetChainParams();
 
 #ifndef WIN32
     CreatePidFile(GetPidFile(), getpid());
 #endif
 
     BCLog::Logger &logger = GetLogger();
 
     bool default_shrinkdebugfile = logger.DefaultShrinkDebugFile();
     if (gArgs.GetBoolArg("-shrinkdebugfile", default_shrinkdebugfile)) {
         // Do this first since it both loads a bunch of debug.log into memory,
         // and because this needs to happen before any other debug.log printing.
         logger.ShrinkDebugFile();
     }
 
     if (logger.m_print_to_file) {
         if (!logger.OpenDebugLog()) {
             return InitError(strprintf("Could not open debug log file %s",
                                        logger.GetDebugLogPath().string()));
         }
     }
 
     if (!logger.m_log_timestamps) {
         LogPrintf("Startup time: %s\n", FormatISO8601DateTime(GetTime()));
     }
     LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
     LogPrintf("Using data directory %s\n", GetDataDir().string());
     LogPrintf(
         "Using config file %s\n",
         GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string());
     LogPrintf("Using at most %i automatic connections (%i file descriptors "
               "available)\n",
               nMaxConnections, nFD);
 
     // Warn about relative -datadir path.
     if (gArgs.IsArgSet("-datadir") &&
         !fs::path(gArgs.GetArg("-datadir", "")).is_absolute()) {
         LogPrintf("Warning: relative datadir option '%s' specified, which will "
                   "be interpreted relative to the current working directory "
                   "'%s'. This is fragile, because if bitcoin is started in the "
                   "future from a different location, it will be unable to "
                   "locate the current data files. There could also be data "
                   "loss if bitcoin is started while in a temporary "
                   "directory.\n",
                   gArgs.GetArg("-datadir", ""), fs::current_path().string());
     }
 
     InitSignatureCache();
     InitScriptExecutionCache();
 
     LogPrintf("Using %u threads for script verification\n",
               nScriptCheckThreads);
     if (nScriptCheckThreads) {
         for (int i = 0; i < nScriptCheckThreads - 1; i++) {
             threadGroup.create_thread(&ThreadScriptCheck);
         }
     }
 
     // Start the lightweight task scheduler thread
     CScheduler::Function serviceLoop =
         boost::bind(&CScheduler::serviceQueue, &scheduler);
     threadGroup.create_thread(boost::bind(&TraceThread<CScheduler::Function>,
                                           "scheduler", serviceLoop));
 
     GetMainSignals().RegisterBackgroundSignalScheduler(scheduler);
     GetMainSignals().RegisterWithMempoolSignals(g_mempool);
 
     /**
      * Start the RPC server.  It will be started in "warmup" mode and not
      * process calls yet (but it will verify that the server is there and will
      * be ready later).  Warmup mode will be completed when initialisation is
      * finished.
      */
     if (gArgs.GetBoolArg("-server", false)) {
         uiInterface.InitMessage.connect(SetRPCWarmupStatus);
         if (!AppInitServers(config, httpRPCRequestProcessor)) {
             return InitError(
                 _("Unable to start HTTP server. See debug log for details."));
         }
     }
 
     // Step 5: verify wallet database integrity
     if (!g_wallet_init_interface->Verify(chainparams)) {
         return false;
     }
 
     // Step 6: network initialization
 
     // Note that we absolutely cannot open any actual connections
     // until the very end ("start node") as the UTXO/block state
     // is not yet setup and may end up being set up twice if we
     // need to reindex later.
 
     assert(!g_connman);
     g_connman = std::unique_ptr<CConnman>(
         new CConnman(config, GetRand(std::numeric_limits<uint64_t>::max()),
                      GetRand(std::numeric_limits<uint64_t>::max())));
     CConnman &connman = *g_connman;
 
     peerLogic.reset(new PeerLogicValidation(&connman, scheduler));
     RegisterValidationInterface(peerLogic.get());
 
     // sanitize comments per BIP-0014, format user agent and check total size
     std::vector<std::string> uacomments;
     for (const std::string &cmt : gArgs.GetArgs("-uacomment")) {
         if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT))
             return InitError(strprintf(
                 _("User Agent comment (%s) contains unsafe characters."), cmt));
         uacomments.push_back(cmt);
     }
     const std::string strSubVersion =
         FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, uacomments);
     if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) {
         return InitError(strprintf(
             _("Total length of network version string (%i) exceeds maximum "
               "length (%i). Reduce the number or size of uacomments."),
             strSubVersion.size(), MAX_SUBVERSION_LENGTH));
     }
 
     if (gArgs.IsArgSet("-onlynet")) {
         std::set<enum Network> nets;
         for (const std::string &snet : gArgs.GetArgs("-onlynet")) {
             enum Network net = ParseNetwork(snet);
             if (net == NET_UNROUTABLE) {
                 return InitError(strprintf(
                     _("Unknown network specified in -onlynet: '%s'"), snet));
             }
             nets.insert(net);
         }
         for (int n = 0; n < NET_MAX; n++) {
             enum Network net = (enum Network)n;
             if (!nets.count(net)) SetLimited(net);
         }
     }
 
     // Check for host lookup allowed before parsing any network related
     // parameters
     fNameLookup = gArgs.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP);
 
     bool proxyRandomize =
         gArgs.GetBoolArg("-proxyrandomize", DEFAULT_PROXYRANDOMIZE);
     // -proxy sets a proxy for all outgoing network traffic
     // -noproxy (or -proxy=0) as well as the empty string can be used to not set
     // a proxy, this is the default
     std::string proxyArg = gArgs.GetArg("-proxy", "");
-    SetLimited(NET_TOR);
+    SetLimited(NET_ONION);
     if (proxyArg != "" && proxyArg != "0") {
         CService proxyAddr;
         if (!Lookup(proxyArg.c_str(), proxyAddr, 9050, fNameLookup)) {
             return InitError(strprintf(
                 _("Invalid -proxy address or hostname: '%s'"), proxyArg));
         }
 
         proxyType addrProxy = proxyType(proxyAddr, proxyRandomize);
         if (!addrProxy.IsValid()) {
             return InitError(strprintf(
                 _("Invalid -proxy address or hostname: '%s'"), proxyArg));
         }
 
         SetProxy(NET_IPV4, addrProxy);
         SetProxy(NET_IPV6, addrProxy);
-        SetProxy(NET_TOR, addrProxy);
+        SetProxy(NET_ONION, addrProxy);
         SetNameProxy(addrProxy);
         // by default, -proxy sets onion as reachable, unless -noonion later
-        SetLimited(NET_TOR, false);
+        SetLimited(NET_ONION, false);
     }
 
     // -onion can be used to set only a proxy for .onion, or override normal
     // proxy for .onion addresses.
     // -noonion (or -onion=0) disables connecting to .onion entirely. An empty
     // string is used to not override the onion proxy (in which case it defaults
     // to -proxy set above, or none)
     std::string onionArg = gArgs.GetArg("-onion", "");
     if (onionArg != "") {
-        if (onionArg == "0") {   // Handle -noonion/-onion=0
-            SetLimited(NET_TOR); // set onions as unreachable
+        if (onionArg == "0") {     // Handle -noonion/-onion=0
+            SetLimited(NET_ONION); // set onions as unreachable
         } else {
             CService onionProxy;
             if (!Lookup(onionArg.c_str(), onionProxy, 9050, fNameLookup)) {
                 return InitError(strprintf(
                     _("Invalid -onion address or hostname: '%s'"), onionArg));
             }
             proxyType addrOnion = proxyType(onionProxy, proxyRandomize);
             if (!addrOnion.IsValid()) {
                 return InitError(strprintf(
                     _("Invalid -onion address or hostname: '%s'"), onionArg));
             }
-            SetProxy(NET_TOR, addrOnion);
-            SetLimited(NET_TOR, false);
+            SetProxy(NET_ONION, addrOnion);
+            SetLimited(NET_ONION, false);
         }
     }
 
     // see Step 2: parameter interactions for more information about these
     fListen = gArgs.GetBoolArg("-listen", DEFAULT_LISTEN);
     fDiscover = gArgs.GetBoolArg("-discover", true);
     fRelayTxes = !gArgs.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY);
 
     for (const std::string &strAddr : gArgs.GetArgs("-externalip")) {
         CService addrLocal;
         if (Lookup(strAddr.c_str(), addrLocal, GetListenPort(), fNameLookup) &&
             addrLocal.IsValid()) {
             AddLocal(addrLocal, LOCAL_MANUAL);
         } else {
             return InitError(ResolveErrMsg("externalip", strAddr));
         }
     }
 
 #if ENABLE_ZMQ
     pzmqNotificationInterface = CZMQNotificationInterface::Create();
 
     if (pzmqNotificationInterface) {
         RegisterValidationInterface(pzmqNotificationInterface);
     }
 #endif
     // unlimited unless -maxuploadtarget is set
     uint64_t nMaxOutboundLimit = 0;
     uint64_t nMaxOutboundTimeframe = MAX_UPLOAD_TIMEFRAME;
 
     if (gArgs.IsArgSet("-maxuploadtarget")) {
         nMaxOutboundLimit =
             gArgs.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET) * 1024 *
             1024;
     }
 
     // Step 7: load block chain
 
     fReindex = gArgs.GetBoolArg("-reindex", false);
     bool fReindexChainState = gArgs.GetBoolArg("-reindex-chainstate", false);
 
     // cache size calculations
     int64_t nTotalCache = (gArgs.GetArg("-dbcache", nDefaultDbCache) << 20);
     // total cache cannot be less than nMinDbCache
     nTotalCache = std::max(nTotalCache, nMinDbCache << 20);
     // total cache cannot be greater than nMaxDbcache
     nTotalCache = std::min(nTotalCache, nMaxDbCache << 20);
     int64_t nBlockTreeDBCache = nTotalCache / 8;
     nBlockTreeDBCache = std::min(nBlockTreeDBCache,
                                  (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)
                                       ? nMaxBlockDBAndTxIndexCache
                                       : nMaxBlockDBCache)
                                      << 20);
     nTotalCache -= nBlockTreeDBCache;
     // use 25%-50% of the remainder for disk cache
     int64_t nCoinDBCache =
         std::min(nTotalCache / 2, (nTotalCache / 4) + (1 << 23));
     // cap total coins db cache
     nCoinDBCache = std::min(nCoinDBCache, nMaxCoinsDBCache << 20);
     nTotalCache -= nCoinDBCache;
     // the rest goes to in-memory cache
     nCoinCacheUsage = nTotalCache;
     int64_t nMempoolSizeMax =
         gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
     LogPrintf("Cache configuration:\n");
     LogPrintf("* Using %.1fMiB for block index database\n",
               nBlockTreeDBCache * (1.0 / 1024 / 1024));
     LogPrintf("* Using %.1fMiB for chain state database\n",
               nCoinDBCache * (1.0 / 1024 / 1024));
     LogPrintf("* Using %.1fMiB for in-memory UTXO set (plus up to %.1fMiB of "
               "unused mempool space)\n",
               nCoinCacheUsage * (1.0 / 1024 / 1024),
               nMempoolSizeMax * (1.0 / 1024 / 1024));
 
     int64_t nStart = 0;
     bool fLoaded = false;
     while (!fLoaded && !fRequestShutdown) {
         bool fReset = fReindex;
         std::string strLoadError;
 
         uiInterface.InitMessage(_("Loading block index..."));
 
         LOCK(cs_main);
 
         nStart = GetTimeMillis();
         do {
             try {
                 UnloadBlockIndex();
                 pcoinsTip.reset();
                 pcoinsdbview.reset();
                 pcoinscatcher.reset();
                 pblocktree.reset(
                     new CBlockTreeDB(nBlockTreeDBCache, false, fReset));
 
                 if (fReindex) {
                     pblocktree->WriteReindexing(true);
                     // If we're reindexing in prune mode, wipe away unusable
                     // block files and all undo data files
                     if (fPruneMode) {
                         CleanupBlockRevFiles();
                     }
                 }
 
                 if (fRequestShutdown) {
                     break;
                 }
 
                 // LoadBlockIndex will load fTxIndex from the db, or set it if
                 // we're reindexing. It will also load fHavePruned if we've
                 // ever removed a block file from disk.
                 if (!LoadBlockIndex(config)) {
                     strLoadError = _("Error loading block database");
                     break;
                 }
 
                 // If the loaded chain has a wrong genesis, bail out immediately
                 // (we're likely using a testnet datadir, or the other way
                 // around).
                 if (!mapBlockIndex.empty() &&
                     !LookupBlockIndex(
                         chainparams.GetConsensus().hashGenesisBlock)) {
                     return InitError(_("Incorrect or no genesis block found. "
                                        "Wrong datadir for network?"));
                 }
 
                 // Check for changed -txindex state
                 if (fTxIndex != gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
                     strLoadError = _("You need to rebuild the database using "
                                      "-reindex-chainstate to change -txindex");
                     break;
                 }
 
                 // Check for changed -prune state.  What we are concerned about
                 // is a user who has pruned blocks in the past, but is now
                 // trying to run unpruned.
                 if (fHavePruned && !fPruneMode) {
                     strLoadError =
                         _("You need to rebuild the database using -reindex to "
                           "go back to unpruned mode.  This will redownload the "
                           "entire blockchain");
                     break;
                 }
 
                 // At this point blocktree args are consistent with what's on
                 // disk. If we're not mid-reindex (based on disk + args), add a
                 // genesis block on disk. This is called again in ThreadImport
                 // if the reindex completes.
                 if (!fReindex && !LoadGenesisBlock(chainparams)) {
                     strLoadError = _("Error initializing block database");
                     break;
                 }
 
                 // At this point we're either in reindex or we've loaded a
                 // useful block tree into mapBlockIndex!
 
                 pcoinsdbview.reset(new CCoinsViewDB(
                     nCoinDBCache, false, fReset || fReindexChainState));
                 pcoinscatcher.reset(
                     new CCoinsViewErrorCatcher(pcoinsdbview.get()));
 
                 // If necessary, upgrade from older database format.
                 // This is a no-op if we cleared the coinsviewdb with -reindex
                 // or -reindex-chainstate
                 if (!pcoinsdbview->Upgrade()) {
                     strLoadError = _("Error upgrading chainstate database");
                     break;
                 }
 
                 // ReplayBlocks is a no-op if we cleared the coinsviewdb with
                 // -reindex or -reindex-chainstate
                 if (!ReplayBlocks(config, pcoinsdbview.get())) {
                     strLoadError =
                         _("Unable to replay blocks. You will need to rebuild "
                           "the database using -reindex-chainstate.");
                     break;
                 }
 
                 // The on-disk coinsdb is now in a good state, create the cache
                 pcoinsTip.reset(new CCoinsViewCache(pcoinscatcher.get()));
 
                 if (!fReindex && !fReindexChainState) {
                     // LoadChainTip sets chainActive based on pcoinsTip's best
                     // block
                     if (!LoadChainTip(config)) {
                         strLoadError = _("Error initializing block database");
                         break;
                     }
                     assert(chainActive.Tip() != nullptr);
                 }
 
                 if (!fReindex) {
                     // Note that RewindBlockIndex MUST run even if we're about
                     // to -reindex-chainstate. It both disconnects blocks based
                     // on chainActive, and drops block data in mapBlockIndex
                     // based on lack of available witness data.
                     uiInterface.InitMessage(_("Rewinding blocks..."));
                     if (!RewindBlockIndex(config)) {
                         strLoadError = _("Unable to rewind the database to a "
                                          "pre-fork state. You will need to "
                                          "redownload the blockchain");
                         break;
                     }
                 }
 
                 if (!fReindex && !fReindexChainState) {
                     uiInterface.InitMessage(_("Verifying blocks..."));
                     if (fHavePruned &&
                         gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) >
                             MIN_BLOCKS_TO_KEEP) {
                         LogPrintf("Prune: pruned datadir may not have more "
                                   "than %d blocks; only checking available "
                                   "blocks",
                                   MIN_BLOCKS_TO_KEEP);
                     }
 
                     CBlockIndex *tip = chainActive.Tip();
                     RPCNotifyBlockChange(true, tip);
                     if (tip && tip->nTime >
                                    GetAdjustedTime() + MAX_FUTURE_BLOCK_TIME) {
                         strLoadError = _(
                             "The block database contains a block which appears "
                             "to be from the future. This may be due to your "
                             "computer's date and time being set incorrectly. "
                             "Only rebuild the block database if you are sure "
                             "that your computer's date and time are correct");
                         break;
                     }
 
                     if (!CVerifyDB().VerifyDB(
                             config, pcoinsdbview.get(),
                             gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL),
                             gArgs.GetArg("-checkblocks",
                                          DEFAULT_CHECKBLOCKS))) {
                         strLoadError = _("Corrupted block database detected");
                         break;
                     }
                 }
             } catch (const std::exception &e) {
                 LogPrintf("%s\n", e.what());
                 strLoadError = _("Error opening block database");
                 break;
             }
 
             fLoaded = true;
         } while (false);
 
         if (!fLoaded && !fRequestShutdown) {
             // first suggest a reindex
             if (!fReset) {
                 bool fRet = uiInterface.ThreadSafeQuestion(
                     strLoadError + ".\n\n" +
                         _("Do you want to rebuild the block database now?"),
                     strLoadError + ".\nPlease restart with -reindex or "
                                    "-reindex-chainstate to recover.",
                     "",
                     CClientUIInterface::MSG_ERROR |
                         CClientUIInterface::BTN_ABORT);
                 if (fRet) {
                     fReindex = true;
                     fRequestShutdown = false;
                 } else {
                     LogPrintf("Aborted block database rebuild. Exiting.\n");
                     return false;
                 }
             } else {
                 return InitError(strLoadError);
             }
         }
     }
 
     // As LoadBlockIndex can take several minutes, it's possible the user
     // requested to kill the GUI during the last operation. If so, exit.
     // As the program has not fully started yet, Shutdown() is possibly
     // overkill.
     if (fRequestShutdown) {
         LogPrintf("Shutdown requested. Exiting.\n");
         return false;
     }
     LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart);
 
     // Encoded addresses using cashaddr instead of base58
     // Activates by default on Jan, 14
     config.SetCashAddrEncoding(
         gArgs.GetBoolArg("-usecashaddr", GetAdjustedTime() > 1515900000));
 
     // Step 8: load wallet
     if (!g_wallet_init_interface->Open(chainparams)) {
         return false;
     }
 
     // Step 9: data directory maintenance
 
     // if pruning, unset the service bit and perform the initial blockstore
     // prune after any wallet rescanning has taken place.
     if (fPruneMode) {
         LogPrintf("Unsetting NODE_NETWORK on prune mode\n");
         nLocalServices = ServiceFlags(nLocalServices & ~NODE_NETWORK);
         if (!fReindex) {
             uiInterface.InitMessage(_("Pruning blockstore..."));
             PruneAndFlush();
         }
     }
 
     // Step 10: import blocks
     if (!CheckDiskSpace()) {
         return false;
     }
 
     // Either install a handler to notify us when genesis activates, or set
     // fHaveGenesis directly.
     // No locking, as this happens before any background thread is started.
     if (chainActive.Tip() == nullptr) {
         uiInterface.NotifyBlockTip.connect(BlockNotifyGenesisWait);
     } else {
         fHaveGenesis = true;
     }
 
     if (gArgs.IsArgSet("-blocknotify")) {
         uiInterface.NotifyBlockTip.connect(BlockNotifyCallback);
     }
 
     std::vector<fs::path> vImportFiles;
     for (const std::string &strFile : gArgs.GetArgs("-loadblock")) {
         vImportFiles.push_back(strFile);
     }
 
     threadGroup.create_thread(
         boost::bind(&ThreadImport, std::ref(config), vImportFiles));
 
     // Wait for genesis block to be processed
     {
         WAIT_LOCK(cs_GenesisWait, lock);
         // We previously could hang here if StartShutdown() is called prior to
         // ThreadImport getting started, so instead we just wait on a timer to
         // check ShutdownRequested() regularly.
         while (!fHaveGenesis && !ShutdownRequested()) {
             condvar_GenesisWait.wait_for(lock, std::chrono::milliseconds(500));
         }
         uiInterface.NotifyBlockTip.disconnect(BlockNotifyGenesisWait);
     }
 
     // Step 11: start node
 
     int chain_active_height;
 
     //// debug print
     {
         LOCK(cs_main);
         LogPrintf("mapBlockIndex.size() = %u\n", mapBlockIndex.size());
         chain_active_height = chainActive.Height();
     }
     LogPrintf("nBestHeight = %d\n", chain_active_height);
 
     if (gArgs.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) {
         StartTorControl();
     }
 
     Discover();
 
     // Map ports with UPnP
     if (gArgs.GetBoolArg("-upnp", DEFAULT_UPNP)) {
         StartMapPort();
     }
 
     CConnman::Options connOptions;
     connOptions.nLocalServices = nLocalServices;
     connOptions.nMaxConnections = nMaxConnections;
     connOptions.nMaxOutbound =
         std::min(MAX_OUTBOUND_CONNECTIONS, connOptions.nMaxConnections);
     connOptions.nMaxAddnode = MAX_ADDNODE_CONNECTIONS;
     connOptions.nMaxFeeler = 1;
     connOptions.nBestHeight = chain_active_height;
     connOptions.uiInterface = &uiInterface;
     connOptions.m_msgproc = peerLogic.get();
     connOptions.nSendBufferMaxSize =
         1000 * gArgs.GetArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER);
     connOptions.nReceiveFloodSize =
         1000 * gArgs.GetArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER);
     connOptions.m_added_nodes = gArgs.GetArgs("-addnode");
 
     connOptions.nMaxOutboundTimeframe = nMaxOutboundTimeframe;
     connOptions.nMaxOutboundLimit = nMaxOutboundLimit;
 
     for (const std::string &strBind : gArgs.GetArgs("-bind")) {
         CService addrBind;
         if (!Lookup(strBind.c_str(), addrBind, GetListenPort(), false)) {
             return InitError(ResolveErrMsg("bind", strBind));
         }
         connOptions.vBinds.push_back(addrBind);
     }
 
     for (const std::string &strBind : gArgs.GetArgs("-whitebind")) {
         CService addrBind;
         if (!Lookup(strBind.c_str(), addrBind, 0, false)) {
             return InitError(ResolveErrMsg("whitebind", strBind));
         }
         if (addrBind.GetPort() == 0) {
             return InitError(strprintf(
                 _("Need to specify a port with -whitebind: '%s'"), strBind));
         }
         connOptions.vWhiteBinds.push_back(addrBind);
     }
 
     for (const auto &net : gArgs.GetArgs("-whitelist")) {
         CSubNet subnet;
         LookupSubNet(net.c_str(), subnet);
         if (!subnet.IsValid()) {
             return InitError(strprintf(
                 _("Invalid netmask specified in -whitelist: '%s'"), net));
         }
         connOptions.vWhitelistedRange.push_back(subnet);
     }
 
     connOptions.vSeedNodes = gArgs.GetArgs("-seednode");
 
     // Initiate outbound connections unless connect=0
     connOptions.m_use_addrman_outgoing = !gArgs.IsArgSet("-connect");
     if (!connOptions.m_use_addrman_outgoing) {
         const auto connect = gArgs.GetArgs("-connect");
         if (connect.size() != 1 || connect[0] != "0") {
             connOptions.m_specified_outgoing = connect;
         }
     }
     if (!connman.Start(scheduler, connOptions)) {
         return false;
     }
 
     // Step 12: finished
 
     SetRPCWarmupFinished();
     uiInterface.InitMessage(_("Done loading"));
 
     g_wallet_init_interface->Start(scheduler);
 
     return !fRequestShutdown;
 }
diff --git a/src/netaddress.cpp b/src/netaddress.cpp
index 82058ab1d..d9d40caaf 100644
--- a/src/netaddress.cpp
+++ b/src/netaddress.cpp
@@ -1,736 +1,736 @@
 // Copyright (c) 2009-2010 Satoshi Nakamoto
 // Copyright (c) 2009-2016 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #ifdef HAVE_CONFIG_H
 #include "config/bitcoin-config.h"
 #endif
 
 #include "hash.h"
 #include "netaddress.h"
 #include "tinyformat.h"
 #include "utilstrencodings.h"
 
 static const uint8_t pchIPv4[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff};
 static const uint8_t pchOnionCat[] = {0xFD, 0x87, 0xD8, 0x7E, 0xEB, 0x43};
 
 // 0xFD + sha256("bitcoin")[0:5]
 static const uint8_t g_internal_prefix[] = {0xFD, 0x6B, 0x88, 0xC0, 0x87, 0x24};
 
 CNetAddr::CNetAddr() {
     memset(ip, 0, sizeof(ip));
     scopeId = 0;
 }
 
 void CNetAddr::SetIP(const CNetAddr &ipIn) {
     memcpy(ip, ipIn.ip, sizeof(ip));
 }
 
 void CNetAddr::SetRaw(Network network, const uint8_t *ip_in) {
     switch (network) {
         case NET_IPV4:
             memcpy(ip, pchIPv4, 12);
             memcpy(ip + 12, ip_in, 4);
             break;
         case NET_IPV6:
             memcpy(ip, ip_in, 16);
             break;
         default:
             assert(!"invalid network");
     }
 }
 
 bool CNetAddr::SetInternal(const std::string &name) {
     if (name.empty()) {
         return false;
     }
     uint8_t hash[32] = {};
     CSHA256().Write((const uint8_t *)name.data(), name.size()).Finalize(hash);
     memcpy(ip, g_internal_prefix, sizeof(g_internal_prefix));
     memcpy(ip + sizeof(g_internal_prefix), hash,
            sizeof(ip) - sizeof(g_internal_prefix));
     return true;
 }
 
 bool CNetAddr::SetSpecial(const std::string &strName) {
     if (strName.size() > 6 &&
         strName.substr(strName.size() - 6, 6) == ".onion") {
         std::vector<uint8_t> vchAddr =
             DecodeBase32(strName.substr(0, strName.size() - 6).c_str());
         if (vchAddr.size() != 16 - sizeof(pchOnionCat)) {
             return false;
         }
         memcpy(ip, pchOnionCat, sizeof(pchOnionCat));
         for (unsigned int i = 0; i < 16 - sizeof(pchOnionCat); i++) {
             ip[i + sizeof(pchOnionCat)] = vchAddr[i];
         }
         return true;
     }
     return false;
 }
 
 CNetAddr::CNetAddr(const struct in_addr &ipv4Addr) {
     SetRaw(NET_IPV4, (const uint8_t *)&ipv4Addr);
 }
 
 CNetAddr::CNetAddr(const struct in6_addr &ipv6Addr, const uint32_t scope) {
     SetRaw(NET_IPV6, (const uint8_t *)&ipv6Addr);
     scopeId = scope;
 }
 
 unsigned int CNetAddr::GetByte(int n) const {
     return ip[15 - n];
 }
 
 bool CNetAddr::IsIPv4() const {
     return (memcmp(ip, pchIPv4, sizeof(pchIPv4)) == 0);
 }
 
 bool CNetAddr::IsIPv6() const {
     return !IsIPv4() && !IsTor() && !IsInternal();
 }
 
 bool CNetAddr::IsRFC1918() const {
     return IsIPv4() &&
            (GetByte(3) == 10 || (GetByte(3) == 192 && GetByte(2) == 168) ||
             (GetByte(3) == 172 && (GetByte(2) >= 16 && GetByte(2) <= 31)));
 }
 
 bool CNetAddr::IsRFC2544() const {
     return IsIPv4() && GetByte(3) == 198 &&
            (GetByte(2) == 18 || GetByte(2) == 19);
 }
 
 bool CNetAddr::IsRFC3927() const {
     return IsIPv4() && (GetByte(3) == 169 && GetByte(2) == 254);
 }
 
 bool CNetAddr::IsRFC6598() const {
     return IsIPv4() && GetByte(3) == 100 && GetByte(2) >= 64 &&
            GetByte(2) <= 127;
 }
 
 bool CNetAddr::IsRFC5737() const {
     return IsIPv4() &&
            ((GetByte(3) == 192 && GetByte(2) == 0 && GetByte(1) == 2) ||
             (GetByte(3) == 198 && GetByte(2) == 51 && GetByte(1) == 100) ||
             (GetByte(3) == 203 && GetByte(2) == 0 && GetByte(1) == 113));
 }
 
 bool CNetAddr::IsRFC3849() const {
     return GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x0D &&
            GetByte(12) == 0xB8;
 }
 
 bool CNetAddr::IsRFC3964() const {
     return (GetByte(15) == 0x20 && GetByte(14) == 0x02);
 }
 
 bool CNetAddr::IsRFC6052() const {
     static const uint8_t pchRFC6052[] = {0, 0x64, 0xFF, 0x9B, 0, 0,
                                          0, 0,    0,    0,    0, 0};
     return (memcmp(ip, pchRFC6052, sizeof(pchRFC6052)) == 0);
 }
 
 bool CNetAddr::IsRFC4380() const {
     return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0 &&
             GetByte(12) == 0);
 }
 
 bool CNetAddr::IsRFC4862() const {
     static const uint8_t pchRFC4862[] = {0xFE, 0x80, 0, 0, 0, 0, 0, 0};
     return (memcmp(ip, pchRFC4862, sizeof(pchRFC4862)) == 0);
 }
 
 bool CNetAddr::IsRFC4193() const {
     return ((GetByte(15) & 0xFE) == 0xFC);
 }
 
 bool CNetAddr::IsRFC6145() const {
     static const uint8_t pchRFC6145[] = {0, 0, 0,    0,    0, 0,
                                          0, 0, 0xFF, 0xFF, 0, 0};
     return (memcmp(ip, pchRFC6145, sizeof(pchRFC6145)) == 0);
 }
 
 bool CNetAddr::IsRFC4843() const {
     return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x00 &&
             (GetByte(12) & 0xF0) == 0x10);
 }
 
 bool CNetAddr::IsTor() const {
     return (memcmp(ip, pchOnionCat, sizeof(pchOnionCat)) == 0);
 }
 
 bool CNetAddr::IsLocal() const {
     // IPv4 loopback
     if (IsIPv4() && (GetByte(3) == 127 || GetByte(3) == 0)) return true;
 
     // IPv6 loopback (::1/128)
     static const uint8_t pchLocal[16] = {0, 0, 0, 0, 0, 0, 0, 0,
                                          0, 0, 0, 0, 0, 0, 0, 1};
     if (memcmp(ip, pchLocal, 16) == 0) return true;
 
     return false;
 }
 
 bool CNetAddr::IsValid() const {
     // Cleanup 3-byte shifted addresses caused by garbage in size field of addr
     // messages from versions before 0.2.9 checksum.
     // Two consecutive addr messages look like this:
     // header20 vectorlen3 addr26 addr26 addr26 header20 vectorlen3 addr26
     // addr26 addr26... so if the first length field is garbled, it reads the
     // second batch of addr misaligned by 3 bytes.
     if (memcmp(ip, pchIPv4 + 3, sizeof(pchIPv4) - 3) == 0) {
         return false;
     }
 
     // unspecified IPv6 address (::/128)
     uint8_t ipNone6[16] = {};
     if (memcmp(ip, ipNone6, 16) == 0) {
         return false;
     }
 
     // documentation IPv6 address
     if (IsRFC3849()) {
         return false;
     }
 
     if (IsInternal()) {
         return false;
     }
 
     if (IsIPv4()) {
         // INADDR_NONE
         uint32_t ipNone = INADDR_NONE;
         if (memcmp(ip + 12, &ipNone, 4) == 0) {
             return false;
         }
 
         // 0
         ipNone = 0;
         if (memcmp(ip + 12, &ipNone, 4) == 0) {
             return false;
         }
     }
 
     return true;
 }
 
 bool CNetAddr::IsRoutable() const {
     return IsValid() &&
            !(IsRFC1918() || IsRFC2544() || IsRFC3927() || IsRFC4862() ||
              IsRFC6598() || IsRFC5737() || (IsRFC4193() && !IsTor()) ||
              IsRFC4843() || IsLocal() || IsInternal());
 }
 
 bool CNetAddr::IsInternal() const {
     return memcmp(ip, g_internal_prefix, sizeof(g_internal_prefix)) == 0;
 }
 
 enum Network CNetAddr::GetNetwork() const {
     if (IsInternal()) {
         return NET_INTERNAL;
     }
 
     if (!IsRoutable()) {
         return NET_UNROUTABLE;
     }
 
     if (IsIPv4()) {
         return NET_IPV4;
     }
 
     if (IsTor()) {
-        return NET_TOR;
+        return NET_ONION;
     }
 
     return NET_IPV6;
 }
 
 std::string CNetAddr::ToStringIP() const {
     if (IsTor()) {
         return EncodeBase32(&ip[6], 10) + ".onion";
     }
     if (IsInternal()) {
         return EncodeBase32(ip + sizeof(g_internal_prefix),
                             sizeof(ip) - sizeof(g_internal_prefix)) +
                ".internal";
     }
     CService serv(*this, 0);
     struct sockaddr_storage sockaddr;
     socklen_t socklen = sizeof(sockaddr);
     if (serv.GetSockAddr((struct sockaddr *)&sockaddr, &socklen)) {
         char name[1025] = "";
         if (!getnameinfo((const struct sockaddr *)&sockaddr, socklen, name,
                          sizeof(name), nullptr, 0, NI_NUMERICHOST)) {
             return std::string(name);
         }
     }
     if (IsIPv4()) {
         return strprintf("%u.%u.%u.%u", GetByte(3), GetByte(2), GetByte(1),
                          GetByte(0));
     }
 
     return strprintf("%x:%x:%x:%x:%x:%x:%x:%x", GetByte(15) << 8 | GetByte(14),
                      GetByte(13) << 8 | GetByte(12),
                      GetByte(11) << 8 | GetByte(10),
                      GetByte(9) << 8 | GetByte(8), GetByte(7) << 8 | GetByte(6),
                      GetByte(5) << 8 | GetByte(4), GetByte(3) << 8 | GetByte(2),
                      GetByte(1) << 8 | GetByte(0));
 }
 
 std::string CNetAddr::ToString() const {
     return ToStringIP();
 }
 
 bool operator==(const CNetAddr &a, const CNetAddr &b) {
     return (memcmp(a.ip, b.ip, 16) == 0);
 }
 
 bool operator<(const CNetAddr &a, const CNetAddr &b) {
     return (memcmp(a.ip, b.ip, 16) < 0);
 }
 
 bool CNetAddr::GetInAddr(struct in_addr *pipv4Addr) const {
     if (!IsIPv4()) {
         return false;
     }
     memcpy(pipv4Addr, ip + 12, 4);
     return true;
 }
 
 bool CNetAddr::GetIn6Addr(struct in6_addr *pipv6Addr) const {
     memcpy(pipv6Addr, ip, 16);
     return true;
 }
 
 // get canonical identifier of an address' group no two connections will be
 // attempted to addresses with the same group
 std::vector<uint8_t> CNetAddr::GetGroup() const {
     std::vector<uint8_t> vchRet;
     int nClass = NET_IPV6;
     int nStartByte = 0;
     int nBits = 16;
 
     // all local addresses belong to the same group
     if (IsLocal()) {
         nClass = 255;
         nBits = 0;
     }
 
     if (IsInternal()) {
         // all internal-usage addresses get their own group
         nClass = NET_INTERNAL;
         nStartByte = sizeof(g_internal_prefix);
         nBits = (sizeof(ip) - sizeof(g_internal_prefix)) * 8;
     } else if (!IsRoutable()) {
         // all other unroutable addresses belong to the same group
         nClass = NET_UNROUTABLE;
         nBits = 0;
     } else if (IsIPv4() || IsRFC6145() || IsRFC6052()) {
         // for IPv4 addresses, '1' + the 16 higher-order bits of the IP includes
         // mapped IPv4, SIIT translated IPv4, and the well-known prefix
         nClass = NET_IPV4;
         nStartByte = 12;
     } else if (IsRFC3964()) {
         // for 6to4 tunnelled addresses, use the encapsulated IPv4 address
         nClass = NET_IPV4;
         nStartByte = 2;
     } else if (IsRFC4380()) {
         // for Teredo-tunnelled IPv6 addresses, use the encapsulated IPv4
         // address
         vchRet.push_back(NET_IPV4);
         vchRet.push_back(GetByte(3) ^ 0xFF);
         vchRet.push_back(GetByte(2) ^ 0xFF);
         return vchRet;
     } else if (IsTor()) {
-        nClass = NET_TOR;
+        nClass = NET_ONION;
         nStartByte = 6;
         nBits = 4;
     } else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 &&
                GetByte(13) == 0x04 && GetByte(12) == 0x70) {
         // for he.net, use /36 groups
         nBits = 36;
     } else {
         // for the rest of the IPv6 network, use /32 groups
         nBits = 32;
     }
 
     vchRet.push_back(nClass);
     while (nBits >= 8) {
         vchRet.push_back(GetByte(15 - nStartByte));
         nStartByte++;
         nBits -= 8;
     }
     if (nBits > 0) {
         vchRet.push_back(GetByte(15 - nStartByte) | ((1 << (8 - nBits)) - 1));
     }
 
     return vchRet;
 }
 
 uint64_t CNetAddr::GetHash() const {
     uint256 hash = Hash(&ip[0], &ip[16]);
     uint64_t nRet;
     memcpy(&nRet, &hash, sizeof(nRet));
     return nRet;
 }
 
 // private extensions to enum Network, only returned by GetExtNetwork, and only
 // used in GetReachabilityFrom
 static const int NET_UNKNOWN = NET_MAX + 0;
 static const int NET_TEREDO = NET_MAX + 1;
 static int GetExtNetwork(const CNetAddr *addr) {
     if (addr == nullptr) {
         return NET_UNKNOWN;
     }
     if (addr->IsRFC4380()) {
         return NET_TEREDO;
     }
     return addr->GetNetwork();
 }
 
 /** Calculates a metric for how reachable (*this) is from a given partner */
 int CNetAddr::GetReachabilityFrom(const CNetAddr *paddrPartner) const {
     enum Reachability {
         REACH_UNREACHABLE,
         REACH_DEFAULT,
         REACH_TEREDO,
         REACH_IPV6_WEAK,
         REACH_IPV4,
         REACH_IPV6_STRONG,
         REACH_PRIVATE
     };
 
     if (!IsRoutable() || IsInternal()) {
         return REACH_UNREACHABLE;
     }
 
     int ourNet = GetExtNetwork(this);
     int theirNet = GetExtNetwork(paddrPartner);
     bool fTunnel = IsRFC3964() || IsRFC6052() || IsRFC6145();
 
     switch (theirNet) {
         case NET_IPV4:
             switch (ourNet) {
                 default:
                     return REACH_DEFAULT;
                 case NET_IPV4:
                     return REACH_IPV4;
             }
         case NET_IPV6:
             switch (ourNet) {
                 default:
                     return REACH_DEFAULT;
                 case NET_TEREDO:
                     return REACH_TEREDO;
                 case NET_IPV4:
                     return REACH_IPV4;
                 // only prefer giving our IPv6 address if it's not tunnelled
                 case NET_IPV6:
                     return fTunnel ? REACH_IPV6_WEAK : REACH_IPV6_STRONG;
             }
-        case NET_TOR:
+        case NET_ONION:
             switch (ourNet) {
                 default:
                     return REACH_DEFAULT;
                 // Tor users can connect to IPv4 as well
                 case NET_IPV4:
                     return REACH_IPV4;
-                case NET_TOR:
+                case NET_ONION:
                     return REACH_PRIVATE;
             }
         case NET_TEREDO:
             switch (ourNet) {
                 default:
                     return REACH_DEFAULT;
                 case NET_TEREDO:
                     return REACH_TEREDO;
                 case NET_IPV6:
                     return REACH_IPV6_WEAK;
                 case NET_IPV4:
                     return REACH_IPV4;
             }
         case NET_UNKNOWN:
         case NET_UNROUTABLE:
         default:
             switch (ourNet) {
                 default:
                     return REACH_DEFAULT;
                 case NET_TEREDO:
                     return REACH_TEREDO;
                 case NET_IPV6:
                     return REACH_IPV6_WEAK;
                 case NET_IPV4:
                     return REACH_IPV4;
                 // either from Tor, or don't care about our address
-                case NET_TOR:
+                case NET_ONION:
                     return REACH_PRIVATE;
             }
     }
 }
 
 CService::CService() : port(0) {}
 
 CService::CService(const CNetAddr &cip, unsigned short portIn)
     : CNetAddr(cip), port(portIn) {}
 
 CService::CService(const struct in_addr &ipv4Addr, unsigned short portIn)
     : CNetAddr(ipv4Addr), port(portIn) {}
 
 CService::CService(const struct in6_addr &ipv6Addr, unsigned short portIn)
     : CNetAddr(ipv6Addr), port(portIn) {}
 
 CService::CService(const struct sockaddr_in &addr)
     : CNetAddr(addr.sin_addr), port(ntohs(addr.sin_port)) {
     assert(addr.sin_family == AF_INET);
 }
 
 CService::CService(const struct sockaddr_in6 &addr)
     : CNetAddr(addr.sin6_addr, addr.sin6_scope_id),
       port(ntohs(addr.sin6_port)) {
     assert(addr.sin6_family == AF_INET6);
 }
 
 bool CService::SetSockAddr(const struct sockaddr *paddr) {
     switch (paddr->sa_family) {
         case AF_INET:
             *this =
                 CService(*reinterpret_cast<const struct sockaddr_in *>(paddr));
             return true;
         case AF_INET6:
             *this =
                 CService(*reinterpret_cast<const struct sockaddr_in6 *>(paddr));
             return true;
         default:
             return false;
     }
 }
 
 unsigned short CService::GetPort() const {
     return port;
 }
 
 bool operator==(const CService &a, const CService &b) {
     return static_cast<CNetAddr>(a) == static_cast<CNetAddr>(b) &&
            a.port == b.port;
 }
 
 bool operator<(const CService &a, const CService &b) {
     return static_cast<CNetAddr>(a) < static_cast<CNetAddr>(b) ||
            (static_cast<CNetAddr>(a) == static_cast<CNetAddr>(b) &&
             a.port < b.port);
 }
 
 bool CService::GetSockAddr(struct sockaddr *paddr, socklen_t *addrlen) const {
     if (IsIPv4()) {
         if (*addrlen < (socklen_t)sizeof(struct sockaddr_in)) {
             return false;
         }
         *addrlen = sizeof(struct sockaddr_in);
         struct sockaddr_in *paddrin =
             reinterpret_cast<struct sockaddr_in *>(paddr);
         memset(paddrin, 0, *addrlen);
         if (!GetInAddr(&paddrin->sin_addr)) {
             return false;
         }
         paddrin->sin_family = AF_INET;
         paddrin->sin_port = htons(port);
         return true;
     }
     if (IsIPv6()) {
         if (*addrlen < (socklen_t)sizeof(struct sockaddr_in6)) {
             return false;
         }
         *addrlen = sizeof(struct sockaddr_in6);
         struct sockaddr_in6 *paddrin6 =
             reinterpret_cast<struct sockaddr_in6 *>(paddr);
         memset(paddrin6, 0, *addrlen);
         if (!GetIn6Addr(&paddrin6->sin6_addr)) {
             return false;
         }
         paddrin6->sin6_scope_id = scopeId;
         paddrin6->sin6_family = AF_INET6;
         paddrin6->sin6_port = htons(port);
         return true;
     }
     return false;
 }
 
 std::vector<uint8_t> CService::GetKey() const {
     std::vector<uint8_t> vKey;
     vKey.resize(18);
     memcpy(&vKey[0], ip, 16);
     vKey[16] = port / 0x100;
     vKey[17] = port & 0x0FF;
     return vKey;
 }
 
 std::string CService::ToStringPort() const {
     return strprintf("%u", port);
 }
 
 std::string CService::ToStringIPPort() const {
     if (IsIPv4() || IsTor() || IsInternal()) {
         return ToStringIP() + ":" + ToStringPort();
     } else {
         return "[" + ToStringIP() + "]:" + ToStringPort();
     }
 }
 
 std::string CService::ToString() const {
     return ToStringIPPort();
 }
 
 CSubNet::CSubNet() : valid(false) {
     memset(netmask, 0, sizeof(netmask));
 }
 
 CSubNet::CSubNet(const CNetAddr &addr, int32_t mask) {
     valid = true;
     network = addr;
     // Default to /32 (IPv4) or /128 (IPv6), i.e. match single address
     memset(netmask, 255, sizeof(netmask));
 
     // IPv4 addresses start at offset 12, and first 12 bytes must match, so just
     // offset n
     const int astartofs = network.IsIPv4() ? 12 : 0;
 
     // Only valid if in range of bits of address
     int32_t n = mask;
     if (n >= 0 && n <= (128 - astartofs * 8)) {
         n += astartofs * 8;
         // Clear bits [n..127]
         for (; n < 128; ++n) {
             netmask[n >> 3] &= ~(1 << (7 - (n & 7)));
         }
     } else {
         valid = false;
     }
 
     // Normalize network according to netmask
     for (int x = 0; x < 16; ++x) {
         network.ip[x] &= netmask[x];
     }
 }
 
 CSubNet::CSubNet(const CNetAddr &addr, const CNetAddr &mask) {
     valid = true;
     network = addr;
     // Default to /32 (IPv4) or /128 (IPv6), i.e. match single address
     memset(netmask, 255, sizeof(netmask));
 
     // IPv4 addresses start at offset 12, and first 12 bytes must match, so just
     // offset n
     const int astartofs = network.IsIPv4() ? 12 : 0;
 
     for (int x = astartofs; x < 16; ++x) {
         netmask[x] = mask.ip[x];
     }
 
     // Normalize network according to netmask
     for (int x = 0; x < 16; ++x) {
         network.ip[x] &= netmask[x];
     }
 }
 
 CSubNet::CSubNet(const CNetAddr &addr) : valid(addr.IsValid()) {
     memset(netmask, 255, sizeof(netmask));
     network = addr;
 }
 
 bool CSubNet::Match(const CNetAddr &addr) const {
     if (!valid || !addr.IsValid()) {
         return false;
     }
     for (int x = 0; x < 16; ++x) {
         if ((addr.ip[x] & netmask[x]) != network.ip[x]) {
             return false;
         }
     }
     return true;
 }
 
 static inline int NetmaskBits(uint8_t x) {
     switch (x) {
         case 0x00:
             return 0;
         case 0x80:
             return 1;
         case 0xc0:
             return 2;
         case 0xe0:
             return 3;
         case 0xf0:
             return 4;
         case 0xf8:
             return 5;
         case 0xfc:
             return 6;
         case 0xfe:
             return 7;
         case 0xff:
             return 8;
         default:
             return -1;
     }
 }
 
 std::string CSubNet::ToString() const {
     /* Parse binary 1{n}0{N-n} to see if mask can be represented as /n */
     int cidr = 0;
     bool valid_cidr = true;
     int n = network.IsIPv4() ? 12 : 0;
     for (; n < 16 && netmask[n] == 0xff; ++n) {
         cidr += 8;
     }
     if (n < 16) {
         int bits = NetmaskBits(netmask[n]);
         if (bits < 0) {
             valid_cidr = false;
         } else {
             cidr += bits;
         }
         ++n;
     }
     for (; n < 16 && valid_cidr; ++n) {
         if (netmask[n] != 0x00) {
             valid_cidr = false;
         }
     }
 
     /* Format output */
     std::string strNetmask;
     if (valid_cidr) {
         strNetmask = strprintf("%u", cidr);
     } else {
         if (network.IsIPv4()) {
             strNetmask = strprintf("%u.%u.%u.%u", netmask[12], netmask[13],
                                    netmask[14], netmask[15]);
         } else {
             strNetmask = strprintf(
                 "%x:%x:%x:%x:%x:%x:%x:%x", netmask[0] << 8 | netmask[1],
                 netmask[2] << 8 | netmask[3], netmask[4] << 8 | netmask[5],
                 netmask[6] << 8 | netmask[7], netmask[8] << 8 | netmask[9],
                 netmask[10] << 8 | netmask[11], netmask[12] << 8 | netmask[13],
                 netmask[14] << 8 | netmask[15]);
         }
     }
 
     return network.ToString() + "/" + strNetmask;
 }
 
 bool CSubNet::IsValid() const {
     return valid;
 }
 
 bool operator==(const CSubNet &a, const CSubNet &b) {
     return a.valid == b.valid && a.network == b.network &&
            !memcmp(a.netmask, b.netmask, 16);
 }
 
 bool operator<(const CSubNet &a, const CSubNet &b) {
     return (a.network < b.network ||
             (a.network == b.network && memcmp(a.netmask, b.netmask, 16) < 0));
 }
diff --git a/src/netaddress.h b/src/netaddress.h
index e02d181ea..26749f8c5 100644
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -1,201 +1,201 @@
 // Copyright (c) 2009-2016 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #ifndef BITCOIN_NETADDRESS_H
 #define BITCOIN_NETADDRESS_H
 
 #if defined(HAVE_CONFIG_H)
 #include "config/bitcoin-config.h"
 #endif
 
 #include "compat.h"
 #include "serialize.h"
 
 #include <cstdint>
 #include <string>
 #include <vector>
 
 enum Network {
     NET_UNROUTABLE = 0,
     NET_IPV4,
     NET_IPV6,
-    NET_TOR,
+    NET_ONION,
     NET_INTERNAL,
 
     NET_MAX,
 };
 
 /** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */
 class CNetAddr {
 protected:
     // in network byte order
     uint8_t ip[16];
     // for scoped/link-local ipv6 addresses
     uint32_t scopeId;
 
 public:
     CNetAddr();
     explicit CNetAddr(const struct in_addr &ipv4Addr);
     void SetIP(const CNetAddr &ip);
 
 private:
     /**
      * Set raw IPv4 or IPv6 address (in network byte order)
      * @note Only NET_IPV4 and NET_IPV6 are allowed for network.
      */
     void SetRaw(Network network, const uint8_t *data);
 
 public:
     /**
      * Transform an arbitrary string into a non-routable ipv6 address.
      * Useful for mapping resolved addresses back to their source.
      */
     bool SetInternal(const std::string &name);
 
     // for Tor addresses
     bool SetSpecial(const std::string &strName);
     // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
     bool IsIPv4() const;
     // IPv6 address (not mapped IPv4, not Tor)
     bool IsIPv6() const;
     // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
     bool IsRFC1918() const;
     // IPv4 inter-network communications (192.18.0.0/15)
     bool IsRFC2544() const;
     // IPv4 ISP-level NAT (100.64.0.0/10)
     bool IsRFC6598() const;
     // IPv4 documentation addresses (192.0.2.0/24, 198.51.100.0/24,
     // 203.0.113.0/24)
     bool IsRFC5737() const;
     // IPv6 documentation address (2001:0DB8::/32)
     bool IsRFC3849() const;
     // IPv4 autoconfig (169.254.0.0/16)
     bool IsRFC3927() const;
     // IPv6 6to4 tunnelling (2002::/16)
     bool IsRFC3964() const;
     // IPv6 unique local (FC00::/7)
     bool IsRFC4193() const;
     // IPv6 Teredo tunnelling (2001::/32)
     bool IsRFC4380() const;
     // IPv6 ORCHID (2001:10::/28)
     bool IsRFC4843() const;
     // IPv6 autoconfig (FE80::/64)
     bool IsRFC4862() const;
     // IPv6 well-known prefix (64:FF9B::/96)
     bool IsRFC6052() const;
     // IPv6 IPv4-translated address (::FFFF:0:0:0/96)
     bool IsRFC6145() const;
     bool IsTor() const;
     bool IsLocal() const;
     bool IsRoutable() const;
     bool IsInternal() const;
     bool IsValid() const;
     enum Network GetNetwork() const;
     std::string ToString() const;
     std::string ToStringIP() const;
     unsigned int GetByte(int n) const;
     uint64_t GetHash() const;
     bool GetInAddr(struct in_addr *pipv4Addr) const;
     std::vector<uint8_t> GetGroup() const;
     int GetReachabilityFrom(const CNetAddr *paddrPartner = nullptr) const;
 
     explicit CNetAddr(const struct in6_addr &pipv6Addr,
                       const uint32_t scope = 0);
     bool GetIn6Addr(struct in6_addr *pipv6Addr) const;
 
     friend bool operator==(const CNetAddr &a, const CNetAddr &b);
     friend bool operator!=(const CNetAddr &a, const CNetAddr &b) {
         return !(a == b);
     }
     friend bool operator<(const CNetAddr &a, const CNetAddr &b);
 
     ADD_SERIALIZE_METHODS;
 
     template <typename Stream, typename Operation>
     inline void SerializationOp(Stream &s, Operation ser_action) {
         READWRITE(FLATDATA(ip));
     }
 
     friend class CSubNet;
 };
 
 class CSubNet {
 protected:
     /// Network (base) address
     CNetAddr network;
     /// Netmask, in network byte order
     uint8_t netmask[16];
     /// Is this value valid? (only used to signal parse errors)
     bool valid;
 
 public:
     CSubNet();
     CSubNet(const CNetAddr &addr, int32_t mask);
     CSubNet(const CNetAddr &addr, const CNetAddr &mask);
 
     // constructor for single ip subnet (<ipv4>/32 or <ipv6>/128)
     explicit CSubNet(const CNetAddr &addr);
 
     bool Match(const CNetAddr &addr) const;
 
     std::string ToString() const;
     bool IsValid() const;
 
     friend bool operator==(const CSubNet &a, const CSubNet &b);
     friend bool operator!=(const CSubNet &a, const CSubNet &b) {
         return !(a == b);
     }
     friend bool operator<(const CSubNet &a, const CSubNet &b);
 
     ADD_SERIALIZE_METHODS;
 
     template <typename Stream, typename Operation>
     inline void SerializationOp(Stream &s, Operation ser_action) {
         READWRITE(network);
         READWRITE(FLATDATA(netmask));
         READWRITE(FLATDATA(valid));
     }
 };
 
 /** A combination of a network address (CNetAddr) and a (TCP) port */
 class CService : public CNetAddr {
 protected:
     // host order
     unsigned short port;
 
 public:
     CService();
     CService(const CNetAddr &ip, unsigned short port);
     CService(const struct in_addr &ipv4Addr, unsigned short port);
     explicit CService(const struct sockaddr_in &addr);
     unsigned short GetPort() const;
     bool GetSockAddr(struct sockaddr *paddr, socklen_t *addrlen) const;
     bool SetSockAddr(const struct sockaddr *paddr);
     friend bool operator==(const CService &a, const CService &b);
     friend bool operator!=(const CService &a, const CService &b) {
         return !(a == b);
     }
     friend bool operator<(const CService &a, const CService &b);
     std::vector<uint8_t> GetKey() const;
     std::string ToString() const;
     std::string ToStringPort() const;
     std::string ToStringIPPort() const;
 
     CService(const struct in6_addr &ipv6Addr, unsigned short port);
     explicit CService(const struct sockaddr_in6 &addr);
 
     ADD_SERIALIZE_METHODS;
 
     template <typename Stream, typename Operation>
     inline void SerializationOp(Stream &s, Operation ser_action) {
         READWRITE(FLATDATA(ip));
         unsigned short portN = htons(port);
         READWRITE(FLATDATA(portN));
         if (ser_action.ForRead()) {
             port = ntohs(portN);
         }
     }
 };
 
 #endif // BITCOIN_NETADDRESS_H
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 7d4c68714..101df4dd8 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -1,783 +1,783 @@
 // Copyright (c) 2009-2010 Satoshi Nakamoto
 // Copyright (c) 2009-2016 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include <netbase.h>
 
 #include <hash.h>
 #include <random.h>
 #include <sync.h>
 #include <uint256.h>
 #include <util.h>
 #include <utilstrencodings.h>
 
 #include <atomic>
 
 #ifndef WIN32
 #include <fcntl.h>
 #endif
 
 #include <boost/algorithm/string/case_conv.hpp> // for to_lower()
 
 #if !defined(MSG_NOSIGNAL)
 #define MSG_NOSIGNAL 0
 #endif
 
 // Settings
 static proxyType proxyInfo[NET_MAX];
 static proxyType nameProxy;
 static CCriticalSection cs_proxyInfos;
 int nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
 bool fNameLookup = DEFAULT_NAME_LOOKUP;
 
 // Need ample time for negotiation for very slow proxies such as Tor
 // (milliseconds)
 static const int SOCKS5_RECV_TIMEOUT = 20 * 1000;
 static std::atomic<bool> interruptSocks5Recv(false);
 
 enum Network ParseNetwork(std::string net) {
     boost::to_lower(net);
     if (net == "ipv4") {
         return NET_IPV4;
     }
     if (net == "ipv6") {
         return NET_IPV6;
     }
     if (net == "onion") {
-        return NET_TOR;
+        return NET_ONION;
     }
     if (net == "tor") {
         LogPrintf("Warning: net name 'tor' is deprecated and will be removed "
                   "in the future. You should use 'onion' instead.\n");
-        return NET_TOR;
+        return NET_ONION;
     }
     return NET_UNROUTABLE;
 }
 
 std::string GetNetworkName(enum Network net) {
     switch (net) {
         case NET_IPV4:
             return "ipv4";
         case NET_IPV6:
             return "ipv6";
-        case NET_TOR:
+        case NET_ONION:
             return "onion";
         default:
             return "";
     }
 }
 
 static bool LookupIntern(const char *pszName, std::vector<CNetAddr> &vIP,
                          unsigned int nMaxSolutions, bool fAllowLookup) {
     vIP.clear();
 
     {
         CNetAddr addr;
         if (addr.SetSpecial(std::string(pszName))) {
             vIP.push_back(addr);
             return true;
         }
     }
 
     struct addrinfo aiHint;
     memset(&aiHint, 0, sizeof(struct addrinfo));
 
     aiHint.ai_socktype = SOCK_STREAM;
     aiHint.ai_protocol = IPPROTO_TCP;
     aiHint.ai_family = AF_UNSPEC;
 #ifdef WIN32
     aiHint.ai_flags = fAllowLookup ? 0 : AI_NUMERICHOST;
 #else
     aiHint.ai_flags = fAllowLookup ? AI_ADDRCONFIG : AI_NUMERICHOST;
 #endif
     struct addrinfo *aiRes = nullptr;
     int nErr = getaddrinfo(pszName, nullptr, &aiHint, &aiRes);
     if (nErr) {
         return false;
     }
 
     struct addrinfo *aiTrav = aiRes;
     while (aiTrav != nullptr &&
            (nMaxSolutions == 0 || vIP.size() < nMaxSolutions)) {
         CNetAddr resolved;
         if (aiTrav->ai_family == AF_INET) {
             assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in));
             resolved =
                 CNetAddr(reinterpret_cast<struct sockaddr_in *>(aiTrav->ai_addr)
                              ->sin_addr);
         }
 
         if (aiTrav->ai_family == AF_INET6) {
             assert(aiTrav->ai_addrlen >= sizeof(sockaddr_in6));
             struct sockaddr_in6 *s6 =
                 reinterpret_cast<struct sockaddr_in6 *>(aiTrav->ai_addr);
             resolved = CNetAddr(s6->sin6_addr, s6->sin6_scope_id);
         }
 
         // Never allow resolving to an internal address. Consider any such
         // result invalid.
         if (!resolved.IsInternal()) {
             vIP.push_back(resolved);
         }
 
         aiTrav = aiTrav->ai_next;
     }
 
     freeaddrinfo(aiRes);
 
     return (vIP.size() > 0);
 }
 
 bool LookupHost(const char *pszName, std::vector<CNetAddr> &vIP,
                 unsigned int nMaxSolutions, bool fAllowLookup) {
     std::string strHost(pszName);
     if (strHost.empty()) {
         return false;
     }
     if (strHost.front() == '[' && strHost.back() == ']') {
         strHost = strHost.substr(1, strHost.size() - 2);
     }
 
     return LookupIntern(strHost.c_str(), vIP, nMaxSolutions, fAllowLookup);
 }
 
 bool LookupHost(const char *pszName, CNetAddr &addr, bool fAllowLookup) {
     std::vector<CNetAddr> vIP;
     LookupHost(pszName, vIP, 1, fAllowLookup);
     if (vIP.empty()) {
         return false;
     }
     addr = vIP.front();
     return true;
 }
 
 bool Lookup(const char *pszName, std::vector<CService> &vAddr, int portDefault,
             bool fAllowLookup, unsigned int nMaxSolutions) {
     if (pszName[0] == 0) {
         return false;
     }
     int port = portDefault;
     std::string hostname = "";
     SplitHostPort(std::string(pszName), port, hostname);
 
     std::vector<CNetAddr> vIP;
     bool fRet =
         LookupIntern(hostname.c_str(), vIP, nMaxSolutions, fAllowLookup);
     if (!fRet) {
         return false;
     }
     vAddr.resize(vIP.size());
     for (unsigned int i = 0; i < vIP.size(); i++) {
         vAddr[i] = CService(vIP[i], port);
     }
     return true;
 }
 
 bool Lookup(const char *pszName, CService &addr, int portDefault,
             bool fAllowLookup) {
     std::vector<CService> vService;
     bool fRet = Lookup(pszName, vService, portDefault, fAllowLookup, 1);
     if (!fRet) {
         return false;
     }
     addr = vService[0];
     return true;
 }
 
 CService LookupNumeric(const char *pszName, int portDefault) {
     CService addr;
     // "1.2:345" will fail to resolve the ip, but will still set the port.
     // If the ip fails to resolve, re-init the result.
     if (!Lookup(pszName, addr, portDefault, false)) {
         addr = CService();
     }
     return addr;
 }
 
 struct timeval MillisToTimeval(int64_t nTimeout) {
     struct timeval timeout;
     timeout.tv_sec = nTimeout / 1000;
     timeout.tv_usec = (nTimeout % 1000) * 1000;
     return timeout;
 }
 
 /** SOCKS version */
 enum SOCKSVersion : uint8_t { SOCKS4 = 0x04, SOCKS5 = 0x05 };
 
 /** Values defined for METHOD in RFC1928 */
 enum SOCKS5Method : uint8_t {
     NOAUTH = 0x00,        //! No authentication required
     GSSAPI = 0x01,        //! GSSAPI
     USER_PASS = 0x02,     //! Username/password
     NO_ACCEPTABLE = 0xff, //! No acceptable methods
 };
 
 /** Values defined for CMD in RFC1928 */
 enum SOCKS5Command : uint8_t {
     CONNECT = 0x01,
     BIND = 0x02,
     UDP_ASSOCIATE = 0x03
 };
 
 /** Values defined for REP in RFC1928 */
 enum SOCKS5Reply : uint8_t {
     SUCCEEDED = 0x00,        //! Succeeded
     GENFAILURE = 0x01,       //! General failure
     NOTALLOWED = 0x02,       //! Connection not allowed by ruleset
     NETUNREACHABLE = 0x03,   //! Network unreachable
     HOSTUNREACHABLE = 0x04,  //! Network unreachable
     CONNREFUSED = 0x05,      //! Connection refused
     TTLEXPIRED = 0x06,       //! TTL expired
     CMDUNSUPPORTED = 0x07,   //! Command not supported
     ATYPEUNSUPPORTED = 0x08, //! Address type not supported
 };
 
 /** Values defined for ATYPE in RFC1928 */
 enum SOCKS5Atyp : uint8_t {
     IPV4 = 0x01,
     DOMAINNAME = 0x03,
     IPV6 = 0x04,
 };
 
 /** Status codes that can be returned by InterruptibleRecv */
 enum class IntrRecvError {
     OK,
     Timeout,
     Disconnected,
     NetworkError,
     Interrupted
 };
 
 /**
  * Read bytes from socket. This will either read the full number of bytes
  * requested or return False on error or timeout.
  * This function can be interrupted by calling InterruptSocks5()
  *
  * @param data Buffer to receive into
  * @param len  Length of data to receive
  * @param timeout  Timeout in milliseconds for receive operation
  *
  * @note This function requires that hSocket is in non-blocking mode.
  */
 static IntrRecvError InterruptibleRecv(uint8_t *data, size_t len, int timeout,
                                        const SOCKET &hSocket) {
     int64_t curTime = GetTimeMillis();
     int64_t endTime = curTime + timeout;
     // Maximum time to wait in one select call. It will take up until this time
     // (in millis) to break off in case of an interruption.
     const int64_t maxWait = 1000;
     while (len > 0 && curTime < endTime) {
         // Optimistically try the recv first
         ssize_t ret = recv(hSocket, (char *)data, len, 0);
         if (ret > 0) {
             len -= ret;
             data += ret;
         } else if (ret == 0) {
             // Unexpected disconnection
             return IntrRecvError::Disconnected;
         } else {
             // Other error or blocking
             int nErr = WSAGetLastError();
             if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK ||
                 nErr == WSAEINVAL) {
                 if (!IsSelectableSocket(hSocket)) {
                     return IntrRecvError::NetworkError;
                 }
                 struct timeval tval =
                     MillisToTimeval(std::min(endTime - curTime, maxWait));
                 fd_set fdset;
                 FD_ZERO(&fdset);
                 FD_SET(hSocket, &fdset);
                 int nRet = select(hSocket + 1, &fdset, nullptr, nullptr, &tval);
                 if (nRet == SOCKET_ERROR) {
                     return IntrRecvError::NetworkError;
                 }
             } else {
                 return IntrRecvError::NetworkError;
             }
         }
         if (interruptSocks5Recv) {
             return IntrRecvError::Interrupted;
         }
         curTime = GetTimeMillis();
     }
     return len == 0 ? IntrRecvError::OK : IntrRecvError::Timeout;
 }
 
 /** Credentials for proxy authentication */
 struct ProxyCredentials {
     std::string username;
     std::string password;
 };
 
 /** Convert SOCKS5 reply to an error message */
 static std::string Socks5ErrorString(uint8_t err) {
     switch (err) {
         case SOCKS5Reply::GENFAILURE:
             return "general failure";
         case SOCKS5Reply::NOTALLOWED:
             return "connection not allowed";
         case SOCKS5Reply::NETUNREACHABLE:
             return "network unreachable";
         case SOCKS5Reply::HOSTUNREACHABLE:
             return "host unreachable";
         case SOCKS5Reply::CONNREFUSED:
             return "connection refused";
         case SOCKS5Reply::TTLEXPIRED:
             return "TTL expired";
         case SOCKS5Reply::CMDUNSUPPORTED:
             return "protocol error";
         case SOCKS5Reply::ATYPEUNSUPPORTED:
             return "address type not supported";
         default:
             return "unknown";
     }
 }
 
 /** Connect using SOCKS5 (as described in RFC1928) */
 static bool Socks5(const std::string &strDest, int port,
                    const ProxyCredentials *auth, const SOCKET &hSocket) {
     IntrRecvError recvr;
     LogPrint(BCLog::NET, "SOCKS5 connecting %s\n", strDest);
     if (strDest.size() > 255) {
         return error("Hostname too long");
     }
     // Accepted authentication methods
     std::vector<uint8_t> vSocks5Init;
     vSocks5Init.push_back(SOCKSVersion::SOCKS5);
     if (auth) {
         vSocks5Init.push_back(0x02); // Number of methods
         vSocks5Init.push_back(SOCKS5Method::NOAUTH);
         vSocks5Init.push_back(SOCKS5Method::USER_PASS);
     } else {
         vSocks5Init.push_back(0x01); // Number of methods
         vSocks5Init.push_back(SOCKS5Method::NOAUTH);
     }
     ssize_t ret = send(hSocket, (const char *)vSocks5Init.data(),
                        vSocks5Init.size(), MSG_NOSIGNAL);
     if (ret != (ssize_t)vSocks5Init.size()) {
         return error("Error sending to proxy");
     }
     uint8_t pchRet1[2];
     if ((recvr = InterruptibleRecv(pchRet1, 2, SOCKS5_RECV_TIMEOUT, hSocket)) !=
         IntrRecvError::OK) {
         LogPrintf("Socks5() connect to %s:%d failed: InterruptibleRecv() "
                   "timeout or other failure\n",
                   strDest, port);
         return false;
     }
     if (pchRet1[0] != SOCKSVersion::SOCKS5) {
         return error("Proxy failed to initialize");
     }
     if (pchRet1[1] == SOCKS5Method::USER_PASS && auth) {
         // Perform username/password authentication (as described in RFC1929)
         std::vector<uint8_t> vAuth;
         // Current (and only) version of user/pass subnegotiation
         vAuth.push_back(0x01);
         if (auth->username.size() > 255 || auth->password.size() > 255) {
             return error("Proxy username or password too long");
         }
         vAuth.push_back(auth->username.size());
         vAuth.insert(vAuth.end(), auth->username.begin(), auth->username.end());
         vAuth.push_back(auth->password.size());
         vAuth.insert(vAuth.end(), auth->password.begin(), auth->password.end());
         ret = send(hSocket, (const char *)vAuth.data(), vAuth.size(),
                    MSG_NOSIGNAL);
         if (ret != (ssize_t)vAuth.size()) {
             return error("Error sending authentication to proxy");
         }
         LogPrint(BCLog::PROXY, "SOCKS5 sending proxy authentication %s:%s\n",
                  auth->username, auth->password);
         uint8_t pchRetA[2];
         if ((recvr = InterruptibleRecv(pchRetA, 2, SOCKS5_RECV_TIMEOUT,
                                        hSocket)) != IntrRecvError::OK) {
             return error("Error reading proxy authentication response");
         }
         if (pchRetA[0] != 0x01 || pchRetA[1] != 0x00) {
             return error("Proxy authentication unsuccessful");
         }
     } else if (pchRet1[1] == SOCKS5Method::NOAUTH) {
         // Perform no authentication
     } else {
         return error("Proxy requested wrong authentication method %02x",
                      pchRet1[1]);
     }
     std::vector<uint8_t> vSocks5;
     // VER protocol version
     vSocks5.push_back(SOCKSVersion::SOCKS5);
     // CMD CONNECT
     vSocks5.push_back(SOCKS5Command::CONNECT);
     // RSV Reserved must be 0
     vSocks5.push_back(0x00);
     // ATYP DOMAINNAME
     vSocks5.push_back(SOCKS5Atyp::DOMAINNAME);
     // Length<=255 is checked at beginning of function
     vSocks5.push_back(strDest.size());
     vSocks5.insert(vSocks5.end(), strDest.begin(), strDest.end());
     vSocks5.push_back((port >> 8) & 0xFF);
     vSocks5.push_back((port >> 0) & 0xFF);
     ret = send(hSocket, (const char *)vSocks5.data(), vSocks5.size(),
                MSG_NOSIGNAL);
     if (ret != (ssize_t)vSocks5.size()) {
         return error("Error sending to proxy");
     }
     uint8_t pchRet2[4];
     if ((recvr = InterruptibleRecv(pchRet2, 4, SOCKS5_RECV_TIMEOUT, hSocket)) !=
         IntrRecvError::OK) {
         if (recvr == IntrRecvError::Timeout) {
             /**
              * If a timeout happens here, this effectively means we timed out
              * while connecting to the remote node. This is very common for Tor,
              * so do not print an error message.
              */
             return false;
         } else {
             return error("Error while reading proxy response");
         }
     }
     if (pchRet2[0] != SOCKSVersion::SOCKS5) {
         return error("Proxy failed to accept request");
     }
     if (pchRet2[1] != SOCKS5Reply::SUCCEEDED) {
         // Failures to connect to a peer that are not proxy errors
         LogPrintf("Socks5() connect to %s:%d failed: %s\n", strDest, port,
                   Socks5ErrorString(pchRet2[1]));
         return false;
     }
     // Reserved field must be 0
     if (pchRet2[2] != 0x00) {
         return error("Error: malformed proxy response");
     }
     uint8_t pchRet3[256];
     switch (pchRet2[3]) {
         case SOCKS5Atyp::IPV4:
             recvr = InterruptibleRecv(pchRet3, 4, SOCKS5_RECV_TIMEOUT, hSocket);
             break;
         case SOCKS5Atyp::IPV6:
             recvr =
                 InterruptibleRecv(pchRet3, 16, SOCKS5_RECV_TIMEOUT, hSocket);
             break;
         case SOCKS5Atyp::DOMAINNAME: {
             recvr = InterruptibleRecv(pchRet3, 1, SOCKS5_RECV_TIMEOUT, hSocket);
             if (recvr != IntrRecvError::OK) {
                 return error("Error reading from proxy");
             }
             int nRecv = pchRet3[0];
             recvr =
                 InterruptibleRecv(pchRet3, nRecv, SOCKS5_RECV_TIMEOUT, hSocket);
             break;
         }
         default:
             return error("Error: malformed proxy response");
     }
     if (recvr != IntrRecvError::OK) {
         return error("Error reading from proxy");
     }
     if ((recvr = InterruptibleRecv(pchRet3, 2, SOCKS5_RECV_TIMEOUT, hSocket)) !=
         IntrRecvError::OK) {
         return error("Error reading from proxy");
     }
     LogPrint(BCLog::NET, "SOCKS5 connected %s\n", strDest);
     return true;
 }
 
 SOCKET CreateSocket(const CService &addrConnect) {
     struct sockaddr_storage sockaddr;
     socklen_t len = sizeof(sockaddr);
     if (!addrConnect.GetSockAddr((struct sockaddr *)&sockaddr, &len)) {
         LogPrintf("Cannot create socket for %s: unsupported network\n",
                   addrConnect.ToString());
         return INVALID_SOCKET;
     }
 
     SOCKET hSocket = socket(((struct sockaddr *)&sockaddr)->sa_family,
                             SOCK_STREAM, IPPROTO_TCP);
     if (hSocket == INVALID_SOCKET) {
         return INVALID_SOCKET;
     }
 
     if (!IsSelectableSocket(hSocket)) {
         CloseSocket(hSocket);
         LogPrintf("Cannot create connection: non-selectable socket created (fd "
                   ">= FD_SETSIZE ?)\n");
         return INVALID_SOCKET;
     }
 
 #ifdef SO_NOSIGPIPE
     int set = 1;
     // Different way of disabling SIGPIPE on BSD
     setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (sockopt_arg_type)&set,
                sizeof(int));
 #endif
 
     // Disable Nagle's algorithm
     SetSocketNoDelay(hSocket);
 
     // Set to non-blocking
     if (!SetSocketNonBlocking(hSocket, true)) {
         CloseSocket(hSocket);
         LogPrintf("ConnectSocketDirectly: Setting socket to non-blocking "
                   "failed, error %s\n",
                   NetworkErrorString(WSAGetLastError()));
     }
     return hSocket;
 }
 
 bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET &hSocket,
                            int nTimeout) {
     struct sockaddr_storage sockaddr;
     socklen_t len = sizeof(sockaddr);
     if (hSocket == INVALID_SOCKET) {
         LogPrintf("Cannot connect to %s: invalid socket\n",
                   addrConnect.ToString());
         return false;
     }
     if (!addrConnect.GetSockAddr((struct sockaddr *)&sockaddr, &len)) {
         LogPrintf("Cannot connect to %s: unsupported network\n",
                   addrConnect.ToString());
         return false;
     }
     if (connect(hSocket, (struct sockaddr *)&sockaddr, len) == SOCKET_ERROR) {
         int nErr = WSAGetLastError();
         // WSAEINVAL is here because some legacy version of winsock uses it
         if (nErr == WSAEINPROGRESS || nErr == WSAEWOULDBLOCK ||
             nErr == WSAEINVAL) {
             struct timeval timeout = MillisToTimeval(nTimeout);
             fd_set fdset;
             FD_ZERO(&fdset);
             FD_SET(hSocket, &fdset);
             int nRet = select(hSocket + 1, nullptr, &fdset, nullptr, &timeout);
             if (nRet == 0) {
                 LogPrint(BCLog::NET, "connection to %s timeout\n",
                          addrConnect.ToString());
                 return false;
             }
             if (nRet == SOCKET_ERROR) {
                 LogPrintf("select() for %s failed: %s\n",
                           addrConnect.ToString(),
                           NetworkErrorString(WSAGetLastError()));
                 return false;
             }
             socklen_t nRetSize = sizeof(nRet);
             if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR,
                            (sockopt_arg_type)&nRet,
                            &nRetSize) == SOCKET_ERROR) {
                 LogPrintf("getsockopt() for %s failed: %s\n",
                           addrConnect.ToString(),
                           NetworkErrorString(WSAGetLastError()));
                 return false;
             }
             if (nRet != 0) {
                 LogPrintf("connect() to %s failed after select(): %s\n",
                           addrConnect.ToString(), NetworkErrorString(nRet));
                 return false;
             }
         }
 #ifdef WIN32
         else if (WSAGetLastError() != WSAEISCONN)
 #else
         else
 #endif
         {
             LogPrintf("connect() to %s failed: %s\n", addrConnect.ToString(),
                       NetworkErrorString(WSAGetLastError()));
             return false;
         }
     }
     return true;
 }
 
 bool SetProxy(enum Network net, const proxyType &addrProxy) {
     assert(net >= 0 && net < NET_MAX);
     if (!addrProxy.IsValid()) {
         return false;
     }
     LOCK(cs_proxyInfos);
     proxyInfo[net] = addrProxy;
     return true;
 }
 
 bool GetProxy(enum Network net, proxyType &proxyInfoOut) {
     assert(net >= 0 && net < NET_MAX);
     LOCK(cs_proxyInfos);
     if (!proxyInfo[net].IsValid()) {
         return false;
     }
     proxyInfoOut = proxyInfo[net];
     return true;
 }
 
 bool SetNameProxy(const proxyType &addrProxy) {
     if (!addrProxy.IsValid()) {
         return false;
     }
     LOCK(cs_proxyInfos);
     nameProxy = addrProxy;
     return true;
 }
 
 bool GetNameProxy(proxyType &nameProxyOut) {
     LOCK(cs_proxyInfos);
     if (!nameProxy.IsValid()) {
         return false;
     }
     nameProxyOut = nameProxy;
     return true;
 }
 
 bool HaveNameProxy() {
     LOCK(cs_proxyInfos);
     return nameProxy.IsValid();
 }
 
 bool IsProxy(const CNetAddr &addr) {
     LOCK(cs_proxyInfos);
     for (int i = 0; i < NET_MAX; i++) {
         if (addr == static_cast<CNetAddr>(proxyInfo[i].proxy)) {
             return true;
         }
     }
     return false;
 }
 
 bool ConnectThroughProxy(const proxyType &proxy, const std::string &strDest,
                          int port, const SOCKET &hSocket, int nTimeout,
                          bool *outProxyConnectionFailed) {
     // first connect to proxy server
     if (!ConnectSocketDirectly(proxy.proxy, hSocket, nTimeout)) {
         if (outProxyConnectionFailed) {
             *outProxyConnectionFailed = true;
         }
         return false;
     }
     // do socks negotiation
     if (proxy.randomize_credentials) {
         ProxyCredentials random_auth;
         static std::atomic_int counter(0);
         random_auth.username = random_auth.password =
             strprintf("%i", counter++);
         if (!Socks5(strDest, (unsigned short)port, &random_auth, hSocket)) {
             return false;
         }
     } else if (!Socks5(strDest, (unsigned short)port, 0, hSocket)) {
         return false;
     }
     return true;
 }
 bool LookupSubNet(const char *pszName, CSubNet &ret) {
     std::string strSubnet(pszName);
     size_t slash = strSubnet.find_last_of('/');
     std::vector<CNetAddr> vIP;
 
     std::string strAddress = strSubnet.substr(0, slash);
     if (LookupHost(strAddress.c_str(), vIP, 1, false)) {
         CNetAddr network = vIP[0];
         if (slash != strSubnet.npos) {
             std::string strNetmask = strSubnet.substr(slash + 1);
             int32_t n;
             // IPv4 addresses start at offset 12, and first 12 bytes must match,
             // so just offset n
             if (ParseInt32(strNetmask, &n)) {
                 // If valid number, assume /24 syntax
                 ret = CSubNet(network, n);
                 return ret.IsValid();
             } else {
                 // If not a valid number, try full netmask syntax
                 // Never allow lookup for netmask
                 if (LookupHost(strNetmask.c_str(), vIP, 1, false)) {
                     ret = CSubNet(network, vIP[0]);
                     return ret.IsValid();
                 }
             }
         } else {
             ret = CSubNet(network);
             return ret.IsValid();
         }
     }
     return false;
 }
 
 #ifdef WIN32
 std::string NetworkErrorString(int err) {
     char buf[256];
     buf[0] = 0;
     if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
                            FORMAT_MESSAGE_IGNORE_INSERTS |
                            FORMAT_MESSAGE_MAX_WIDTH_MASK,
                        nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                        buf, sizeof(buf), nullptr)) {
         return strprintf("%s (%d)", buf, err);
     } else {
         return strprintf("Unknown error (%d)", err);
     }
 }
 #else
 std::string NetworkErrorString(int err) {
     char buf[256];
     const char *s = buf;
     buf[0] = 0;
 /* Too bad there are two incompatible implementations of the
  * thread-safe strerror. */
 #ifdef STRERROR_R_CHAR_P
     /* GNU variant can return a pointer outside the passed buffer */
     s = strerror_r(err, buf, sizeof(buf));
 #else
     /* POSIX variant always returns message in buffer */
     if (strerror_r(err, buf, sizeof(buf))) {
         buf[0] = 0;
     }
 #endif
     return strprintf("%s (%d)", s, err);
 }
 #endif
 
 bool CloseSocket(SOCKET &hSocket) {
     if (hSocket == INVALID_SOCKET) {
         return false;
     }
 #ifdef WIN32
     int ret = closesocket(hSocket);
 #else
     int ret = close(hSocket);
 #endif
     hSocket = INVALID_SOCKET;
     return ret != SOCKET_ERROR;
 }
 
 bool SetSocketNonBlocking(const SOCKET &hSocket, bool fNonBlocking) {
     if (fNonBlocking) {
 #ifdef WIN32
         u_long nOne = 1;
         if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) {
 #else
         int fFlags = fcntl(hSocket, F_GETFL, 0);
         if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == SOCKET_ERROR) {
 #endif
             return false;
         }
     } else {
 #ifdef WIN32
         u_long nZero = 0;
         if (ioctlsocket(hSocket, FIONBIO, &nZero) == SOCKET_ERROR) {
 #else
         int fFlags = fcntl(hSocket, F_GETFL, 0);
         if (fcntl(hSocket, F_SETFL, fFlags & ~O_NONBLOCK) == SOCKET_ERROR) {
 #endif
             return false;
         }
     }
 
     return true;
 }
 
 bool SetSocketNoDelay(const SOCKET &hSocket) {
     int set = 1;
     int rc = setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY,
                         (sockopt_arg_type)&set, sizeof(int));
     return rc == 0;
 }
 
 void InterruptSocks5(bool interrupt) {
     interruptSocks5Recv = interrupt;
 }
diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp
index a0264086e..1689773ac 100644
--- a/src/qt/optionsdialog.cpp
+++ b/src/qt/optionsdialog.cpp
@@ -1,332 +1,332 @@
 // Copyright (c) 2011-2016 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #if defined(HAVE_CONFIG_H)
 #include "config/bitcoin-config.h"
 #endif
 
 #include "optionsdialog.h"
 #include "ui_optionsdialog.h"
 
 #include "bitcoinunits.h"
 #include "guiutil.h"
 #include "optionsmodel.h"
 
 #include "netbase.h"
 #include "txdb.h"       // for -dbcache defaults
 #include "validation.h" // for DEFAULT_SCRIPTCHECK_THREADS and MAX_SCRIPTCHECK_THREADS
 
 #include <QDataWidgetMapper>
 #include <QDir>
 #include <QIntValidator>
 #include <QLocale>
 #include <QMessageBox>
 #include <QTimer>
 
 OptionsDialog::OptionsDialog(QWidget *parent, bool enableWallet)
     : QDialog(parent), ui(new Ui::OptionsDialog), model(0), mapper(0) {
     ui->setupUi(this);
 
     /* Main elements init */
     ui->databaseCache->setMinimum(nMinDbCache);
     ui->databaseCache->setMaximum(nMaxDbCache);
     ui->threadsScriptVerif->setMinimum(-GetNumCores());
     ui->threadsScriptVerif->setMaximum(MAX_SCRIPTCHECK_THREADS);
 
 /* Network elements init */
 #ifndef USE_UPNP
     ui->mapPortUpnp->setEnabled(false);
 #endif
 
     ui->proxyIp->setEnabled(false);
     ui->proxyPort->setEnabled(false);
     ui->proxyPort->setValidator(new QIntValidator(1, 65535, this));
 
     ui->proxyIpTor->setEnabled(false);
     ui->proxyPortTor->setEnabled(false);
     ui->proxyPortTor->setValidator(new QIntValidator(1, 65535, this));
 
     connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyIp,
             SLOT(setEnabled(bool)));
     connect(ui->connectSocks, SIGNAL(toggled(bool)), ui->proxyPort,
             SLOT(setEnabled(bool)));
     connect(ui->connectSocks, SIGNAL(toggled(bool)), this,
             SLOT(updateProxyValidationState()));
 
     connect(ui->connectSocksTor, SIGNAL(toggled(bool)), ui->proxyIpTor,
             SLOT(setEnabled(bool)));
     connect(ui->connectSocksTor, SIGNAL(toggled(bool)), ui->proxyPortTor,
             SLOT(setEnabled(bool)));
     connect(ui->connectSocksTor, SIGNAL(toggled(bool)), this,
             SLOT(updateProxyValidationState()));
 
 /* Window elements init */
 #ifdef Q_OS_MAC
     /* remove Window tab on Mac */
     ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabWindow));
 #endif
 
     /* remove Wallet tab in case of -disablewallet */
     if (!enableWallet) {
         ui->tabWidget->removeTab(ui->tabWidget->indexOf(ui->tabWallet));
     }
 
     /* Display elements init */
     QDir translations(":translations");
 
     ui->bitcoinAtStartup->setToolTip(
         ui->bitcoinAtStartup->toolTip().arg(tr(PACKAGE_NAME)));
     ui->bitcoinAtStartup->setText(
         ui->bitcoinAtStartup->text().arg(tr(PACKAGE_NAME)));
 
     ui->lang->setToolTip(ui->lang->toolTip().arg(tr(PACKAGE_NAME)));
     ui->lang->addItem(QString("(") + tr("default") + QString(")"),
                       QVariant(""));
     for (const QString &langStr : translations.entryList()) {
         QLocale locale(langStr);
 
         /** check if the locale name consists of 2 parts (language_country) */
         if (langStr.contains("_")) {
             /** display language strings as "native language - native country
              * (locale name)", e.g. "Deutsch - Deutschland (de)" */
             ui->lang->addItem(locale.nativeLanguageName() + QString(" - ") +
                                   locale.nativeCountryName() + QString(" (") +
                                   langStr + QString(")"),
                               QVariant(langStr));
         } else {
             /** display language strings as "native language (locale name)",
              * e.g. "Deutsch (de)" */
             ui->lang->addItem(locale.nativeLanguageName() + QString(" (") +
                                   langStr + QString(")"),
                               QVariant(langStr));
         }
     }
     ui->thirdPartyTxUrls->setPlaceholderText("https://example.com/tx/%s");
 
     ui->unit->setModel(new BitcoinUnits(this));
 
     /* Widget-to-option mapper */
     mapper = new QDataWidgetMapper(this);
     mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
     mapper->setOrientation(Qt::Vertical);
 
     /* setup/change UI elements when proxy IPs are invalid/valid */
     ui->proxyIp->setCheckValidator(new ProxyAddressValidator(parent));
     ui->proxyIpTor->setCheckValidator(new ProxyAddressValidator(parent));
     connect(ui->proxyIp, SIGNAL(validationDidChange(QValidatedLineEdit *)),
             this, SLOT(updateProxyValidationState()));
     connect(ui->proxyIpTor, SIGNAL(validationDidChange(QValidatedLineEdit *)),
             this, SLOT(updateProxyValidationState()));
     connect(ui->proxyPort, SIGNAL(textChanged(const QString &)), this,
             SLOT(updateProxyValidationState()));
     connect(ui->proxyPortTor, SIGNAL(textChanged(const QString &)), this,
             SLOT(updateProxyValidationState()));
 }
 
 OptionsDialog::~OptionsDialog() {
     delete ui;
 }
 
 void OptionsDialog::setModel(OptionsModel *_model) {
     this->model = _model;
 
     if (_model) {
         /* check if client restart is needed and show persistent message */
         if (_model->isRestartRequired()) showRestartWarning(true);
 
         QString strLabel = _model->getOverriddenByCommandLine();
         if (strLabel.isEmpty()) strLabel = tr("none");
         ui->overriddenByCommandLineLabel->setText(strLabel);
 
         mapper->setModel(_model);
         setMapper();
         mapper->toFirst();
 
         updateDefaultProxyNets();
     }
 
     /* warn when one of the following settings changes by user action (placed
      * here so init via mapper doesn't trigger them) */
 
     /* Main */
     connect(ui->databaseCache, SIGNAL(valueChanged(int)), this,
             SLOT(showRestartWarning()));
     connect(ui->threadsScriptVerif, SIGNAL(valueChanged(int)), this,
             SLOT(showRestartWarning()));
     /* Wallet */
     connect(ui->spendZeroConfChange, SIGNAL(clicked(bool)), this,
             SLOT(showRestartWarning()));
     /* Network */
     connect(ui->allowIncoming, SIGNAL(clicked(bool)), this,
             SLOT(showRestartWarning()));
     connect(ui->connectSocks, SIGNAL(clicked(bool)), this,
             SLOT(showRestartWarning()));
     connect(ui->connectSocksTor, SIGNAL(clicked(bool)), this,
             SLOT(showRestartWarning()));
     /* Display */
     connect(ui->lang, SIGNAL(valueChanged()), this, SLOT(showRestartWarning()));
     connect(ui->thirdPartyTxUrls, SIGNAL(textChanged(const QString &)), this,
             SLOT(showRestartWarning()));
 }
 
 void OptionsDialog::setMapper() {
     /* Main */
     mapper->addMapping(ui->bitcoinAtStartup, OptionsModel::StartAtStartup);
     mapper->addMapping(ui->threadsScriptVerif,
                        OptionsModel::ThreadsScriptVerif);
     mapper->addMapping(ui->databaseCache, OptionsModel::DatabaseCache);
 
     /* Wallet */
     mapper->addMapping(ui->spendZeroConfChange,
                        OptionsModel::SpendZeroConfChange);
     mapper->addMapping(ui->coinControlFeatures,
                        OptionsModel::CoinControlFeatures);
 
     /* Network */
     mapper->addMapping(ui->mapPortUpnp, OptionsModel::MapPortUPnP);
     mapper->addMapping(ui->allowIncoming, OptionsModel::Listen);
 
     mapper->addMapping(ui->connectSocks, OptionsModel::ProxyUse);
     mapper->addMapping(ui->proxyIp, OptionsModel::ProxyIP);
     mapper->addMapping(ui->proxyPort, OptionsModel::ProxyPort);
 
     mapper->addMapping(ui->connectSocksTor, OptionsModel::ProxyUseTor);
     mapper->addMapping(ui->proxyIpTor, OptionsModel::ProxyIPTor);
     mapper->addMapping(ui->proxyPortTor, OptionsModel::ProxyPortTor);
 
 /* Window */
 #ifndef Q_OS_MAC
     mapper->addMapping(ui->hideTrayIcon, OptionsModel::HideTrayIcon);
     mapper->addMapping(ui->minimizeToTray, OptionsModel::MinimizeToTray);
     mapper->addMapping(ui->minimizeOnClose, OptionsModel::MinimizeOnClose);
 #endif
 
     /* Display */
     mapper->addMapping(ui->lang, OptionsModel::Language);
     mapper->addMapping(ui->unit, OptionsModel::DisplayUnit);
     mapper->addMapping(ui->thirdPartyTxUrls, OptionsModel::ThirdPartyTxUrls);
 }
 
 void OptionsDialog::setOkButtonState(bool fState) {
     ui->okButton->setEnabled(fState);
 }
 
 void OptionsDialog::on_resetButton_clicked() {
     if (model) {
         // confirmation dialog
         QMessageBox::StandardButton btnRetVal = QMessageBox::question(
             this, tr("Confirm options reset"),
             tr("Client restart required to activate changes.") + "<br><br>" +
                 tr("Client will be shut down. Do you want to proceed?"),
             QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
 
         if (btnRetVal == QMessageBox::Cancel) return;
 
         /* reset all options and close GUI */
         model->Reset();
         QApplication::quit();
     }
 }
 
 void OptionsDialog::on_okButton_clicked() {
     mapper->submit();
     accept();
     updateDefaultProxyNets();
 }
 
 void OptionsDialog::on_cancelButton_clicked() {
     reject();
 }
 
 void OptionsDialog::on_hideTrayIcon_stateChanged(int fState) {
     if (fState) {
         ui->minimizeToTray->setChecked(false);
         ui->minimizeToTray->setEnabled(false);
     } else {
         ui->minimizeToTray->setEnabled(true);
     }
 }
 
 void OptionsDialog::showRestartWarning(bool fPersistent) {
     ui->statusLabel->setStyleSheet("QLabel { color: red; }");
 
     if (fPersistent) {
         ui->statusLabel->setText(
             tr("Client restart required to activate changes."));
     } else {
         ui->statusLabel->setText(
             tr("This change would require a client restart."));
         // clear non-persistent status label after 10 seconds
         // TODO: should perhaps be a class attribute, if we extend the use of
         // statusLabel
         QTimer::singleShot(10000, this, SLOT(clearStatusLabel()));
     }
 }
 
 void OptionsDialog::clearStatusLabel() {
     ui->statusLabel->clear();
     if (model && model->isRestartRequired()) {
         showRestartWarning(true);
     }
 }
 
 void OptionsDialog::updateProxyValidationState() {
     QValidatedLineEdit *pUiProxyIp = ui->proxyIp;
     QValidatedLineEdit *otherProxyWidget =
         (pUiProxyIp == ui->proxyIpTor) ? ui->proxyIp : ui->proxyIpTor;
     if (pUiProxyIp->isValid() &&
         (!ui->proxyPort->isEnabled() || ui->proxyPort->text().toInt() > 0) &&
         (!ui->proxyPortTor->isEnabled() ||
          ui->proxyPortTor->text().toInt() > 0)) {
         // Only enable ok button if both proxys are valid
         setOkButtonState(otherProxyWidget->isValid());
         clearStatusLabel();
     } else {
         setOkButtonState(false);
         ui->statusLabel->setStyleSheet("QLabel { color: red; }");
         ui->statusLabel->setText(tr("The supplied proxy address is invalid."));
     }
 }
 
 void OptionsDialog::updateDefaultProxyNets() {
     proxyType proxy;
     std::string strProxy;
     QString strDefaultProxyGUI;
 
     GetProxy(NET_IPV4, proxy);
     strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort();
     strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
     (strProxy == strDefaultProxyGUI.toStdString())
         ? ui->proxyReachIPv4->setChecked(true)
         : ui->proxyReachIPv4->setChecked(false);
 
     GetProxy(NET_IPV6, proxy);
     strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort();
     strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
     (strProxy == strDefaultProxyGUI.toStdString())
         ? ui->proxyReachIPv6->setChecked(true)
         : ui->proxyReachIPv6->setChecked(false);
 
-    GetProxy(NET_TOR, proxy);
+    GetProxy(NET_ONION, proxy);
     strProxy = proxy.proxy.ToStringIP() + ":" + proxy.proxy.ToStringPort();
     strDefaultProxyGUI = ui->proxyIp->text() + ":" + ui->proxyPort->text();
     (strProxy == strDefaultProxyGUI.toStdString())
         ? ui->proxyReachTor->setChecked(true)
         : ui->proxyReachTor->setChecked(false);
 }
 
 ProxyAddressValidator::ProxyAddressValidator(QObject *parent)
     : QValidator(parent) {}
 
 QValidator::State ProxyAddressValidator::validate(QString &input,
                                                   int &pos) const {
     Q_UNUSED(pos);
     // Validate the proxy
     CService serv(
         LookupNumeric(input.toStdString().c_str(), DEFAULT_GUI_PROXY_PORT));
     proxyType addrProxy = proxyType(serv, true);
     if (addrProxy.IsValid()) return QValidator::Acceptable;
 
     return QValidator::Invalid;
 }
diff --git a/src/seeder/main.cpp b/src/seeder/main.cpp
index 0ebd7b7b6..bd2d0ca5c 100644
--- a/src/seeder/main.cpp
+++ b/src/seeder/main.cpp
@@ -1,573 +1,573 @@
 #include "bitcoin.h"
 #include "clientversion.h"
 #include "db.h"
 #include "dns.h"
 #include "logging.h"
 #include "protocol.h"
 #include "streams.h"
 
 #include <algorithm>
 #include <atomic>
 #include <cinttypes>
 #include <csignal>
 #include <cstdio>
 #include <cstdlib>
 #include <getopt.h>
 #include <pthread.h>
 
 class CDnsSeedOpts {
 public:
     int nThreads;
     int nPort;
     int nDnsThreads;
     int fUseTestNet;
     int fWipeBan;
     int fWipeIgnore;
     const char *mbox;
     const char *ns;
     const char *host;
     const char *tor;
     const char *ipv4_proxy;
     const char *ipv6_proxy;
     std::set<uint64_t> filter_whitelist;
 
     CDnsSeedOpts()
         : nThreads(96), nPort(53), nDnsThreads(4), fUseTestNet(false),
           fWipeBan(false), fWipeIgnore(false), mbox(nullptr), ns(nullptr),
           host(nullptr), tor(nullptr), ipv4_proxy(nullptr),
           ipv6_proxy(nullptr) {}
 
     void ParseCommandLine(int argc, char **argv) {
         static const char *help =
             "Bitcoin-cash-seeder\n"
             "Usage: %s -h <host> -n <ns> [-m <mbox>] [-t <threads>] [-p "
             "<port>]\n"
             "\n"
             "Options:\n"
             "-h <host>       Hostname of the DNS seed\n"
             "-n <ns>         Hostname of the nameserver\n"
             "-m <mbox>       E-Mail address reported in SOA records\n"
             "-t <threads>    Number of crawlers to run in parallel (default "
             "96)\n"
             "-d <threads>    Number of DNS server threads (default 4)\n"
             "-p <port>       UDP port to listen on (default 53)\n"
             "-o <ip:port>    Tor proxy IP/Port\n"
             "-i <ip:port>    IPV4 SOCKS5 proxy IP/Port\n"
             "-k <ip:port>    IPV6 SOCKS5 proxy IP/Port\n"
             "-w f1,f2,...    Allow these flag combinations as filters\n"
             "--testnet       Use testnet\n"
             "--wipeban       Wipe list of banned nodes\n"
             "--wipeignore    Wipe list of ignored nodes\n"
             "-?, --help      Show this text\n"
             "\n";
         bool showHelp = false;
 
         while (1) {
             static struct option long_options[] = {
                 {"host", required_argument, 0, 'h'},
                 {"ns", required_argument, 0, 'n'},
                 {"mbox", required_argument, 0, 'm'},
                 {"threads", required_argument, 0, 't'},
                 {"dnsthreads", required_argument, 0, 'd'},
                 {"port", required_argument, 0, 'p'},
                 {"onion", required_argument, 0, 'o'},
                 {"proxyipv4", required_argument, 0, 'i'},
                 {"proxyipv6", required_argument, 0, 'k'},
                 {"filter", required_argument, 0, 'w'},
                 {"testnet", no_argument, &fUseTestNet, 1},
                 {"wipeban", no_argument, &fWipeBan, 1},
                 {"wipeignore", no_argument, &fWipeBan, 1},
                 {"help", no_argument, 0, 'h'},
                 {0, 0, 0, 0}};
             int option_index = 0;
             int c =
                 getopt_long(argc, argv, "h:n:m:t:p:d:o:i:k:w:", long_options,
                             &option_index);
             if (c == -1) break;
             switch (c) {
                 case 'h': {
                     host = optarg;
                     break;
                 }
 
                 case 'm': {
                     mbox = optarg;
                     break;
                 }
 
                 case 'n': {
                     ns = optarg;
                     break;
                 }
 
                 case 't': {
                     int n = strtol(optarg, nullptr, 10);
                     if (n > 0 && n < 1000) nThreads = n;
                     break;
                 }
 
                 case 'd': {
                     int n = strtol(optarg, nullptr, 10);
                     if (n > 0 && n < 1000) nDnsThreads = n;
                     break;
                 }
 
                 case 'p': {
                     int p = strtol(optarg, nullptr, 10);
                     if (p > 0 && p < 65536) nPort = p;
                     break;
                 }
 
                 case 'o': {
                     tor = optarg;
                     break;
                 }
 
                 case 'i': {
                     ipv4_proxy = optarg;
                     break;
                 }
 
                 case 'k': {
                     ipv6_proxy = optarg;
                     break;
                 }
 
                 case 'w': {
                     char *ptr = optarg;
                     while (*ptr != 0) {
                         unsigned long l = strtoul(ptr, &ptr, 0);
                         if (*ptr == ',') {
                             ptr++;
                         } else if (*ptr != 0) {
                             break;
                         }
                         filter_whitelist.insert(l);
                     }
                     break;
                 }
 
                 case '?': {
                     showHelp = true;
                     break;
                 }
             }
         }
         if (filter_whitelist.empty()) {
             filter_whitelist.insert(NODE_NETWORK);
             filter_whitelist.insert(NODE_NETWORK | NODE_BLOOM);
             filter_whitelist.insert(NODE_NETWORK | NODE_XTHIN);
             filter_whitelist.insert(NODE_NETWORK | NODE_BLOOM | NODE_XTHIN);
         }
         if (host != nullptr && ns == nullptr) showHelp = true;
         if (showHelp) fprintf(stderr, help, argv[0]);
     }
 };
 
 extern "C" {
 #include "dns.h"
 }
 
 CAddrDb db;
 
 extern "C" void *ThreadCrawler(void *data) {
     int *nThreads = (int *)data;
     do {
         std::vector<CServiceResult> ips;
         int wait = 5;
         db.GetMany(ips, 16, wait);
         int64_t now = time(nullptr);
         if (ips.empty()) {
             wait *= 1000;
             wait += rand() % (500 * *nThreads);
             Sleep(wait);
             continue;
         }
 
         std::vector<CAddress> addr;
         for (size_t i = 0; i < ips.size(); i++) {
             CServiceResult &res = ips[i];
             res.nBanTime = 0;
             res.nClientV = 0;
             res.nHeight = 0;
             res.strClientV = "";
             bool getaddr = res.ourLastSuccess + 86400 < now;
             res.fGood = TestNode(res.service, res.nBanTime, res.nClientV,
                                  res.strClientV, res.nHeight,
                                  getaddr ? &addr : nullptr);
         }
 
         db.ResultMany(ips);
         db.Add(addr);
     } while (1);
     return nullptr;
 }
 
 extern "C" uint32_t GetIPList(void *thread, char *requestedHostname,
                               addr_t *addr, uint32_t max, uint32_t ipv4,
                               uint32_t ipv6);
 
 class CDnsThread {
 public:
     struct FlagSpecificData {
         int nIPv4, nIPv6;
         std::vector<addr_t> cache;
         time_t cacheTime;
         unsigned int cacheHits;
         FlagSpecificData() : nIPv4(0), nIPv6(0), cacheTime(0), cacheHits(0) {}
     };
 
     dns_opt_t dns_opt; // must be first
     const int id;
     std::map<uint64_t, FlagSpecificData> perflag;
     std::atomic<uint64_t> dbQueries;
     std::set<uint64_t> filterWhitelist;
 
     void cacheHit(uint64_t requestedFlags, bool force = false) {
         static bool nets[NET_MAX] = {};
         if (!nets[NET_IPV4]) {
             nets[NET_IPV4] = true;
             nets[NET_IPV6] = true;
         }
         time_t now = time(nullptr);
         FlagSpecificData &thisflag = perflag[requestedFlags];
         thisflag.cacheHits++;
         if (force ||
             thisflag.cacheHits * 400 >
                 (thisflag.cache.size() * thisflag.cache.size()) ||
             (thisflag.cacheHits * thisflag.cacheHits * 20 >
                  thisflag.cache.size() &&
              (now - thisflag.cacheTime > 5))) {
             std::set<CNetAddr> ips;
             db.GetIPs(ips, requestedFlags, 1000, nets);
             dbQueries++;
             thisflag.cache.clear();
             thisflag.nIPv4 = 0;
             thisflag.nIPv6 = 0;
             thisflag.cache.reserve(ips.size());
             for (auto &ip : ips) {
                 struct in_addr addr;
                 struct in6_addr addr6;
                 if (ip.GetInAddr(&addr)) {
                     addr_t a;
                     a.v = 4;
                     memcpy(&a.data.v4, &addr, 4);
                     thisflag.cache.push_back(a);
                     thisflag.nIPv4++;
                 } else if (ip.GetIn6Addr(&addr6)) {
                     addr_t a;
                     a.v = 6;
                     memcpy(&a.data.v6, &addr6, 16);
                     thisflag.cache.push_back(a);
                     thisflag.nIPv6++;
                 }
             }
             thisflag.cacheHits = 0;
             thisflag.cacheTime = now;
         }
     }
 
     CDnsThread(CDnsSeedOpts *opts, int idIn) : id(idIn) {
         dns_opt.host = opts->host;
         dns_opt.ns = opts->ns;
         dns_opt.mbox = opts->mbox;
         dns_opt.datattl = 3600;
         dns_opt.nsttl = 40000;
         dns_opt.cb = GetIPList;
         dns_opt.port = opts->nPort;
         dns_opt.nRequests = 0;
         dbQueries = 0;
         perflag.clear();
         filterWhitelist = opts->filter_whitelist;
     }
 
     void run() { dnsserver(&dns_opt); }
 };
 
 extern "C" uint32_t GetIPList(void *data, char *requestedHostname, addr_t *addr,
                               uint32_t max, uint32_t ipv4, uint32_t ipv6) {
     CDnsThread *thread = (CDnsThread *)data;
 
     uint64_t requestedFlags = 0;
     int hostlen = strlen(requestedHostname);
     if (hostlen > 1 && requestedHostname[0] == 'x' &&
         requestedHostname[1] != '0') {
         char *pEnd;
         uint64_t flags = (uint64_t)strtoull(requestedHostname + 1, &pEnd, 16);
         if (*pEnd == '.' && pEnd <= requestedHostname + 17 &&
             std::find(thread->filterWhitelist.begin(),
                       thread->filterWhitelist.end(),
                       flags) != thread->filterWhitelist.end()) {
             requestedFlags = flags;
         } else {
             return 0;
         }
     } else if (strcasecmp(requestedHostname, thread->dns_opt.host)) {
         return 0;
     }
     thread->cacheHit(requestedFlags);
     auto &thisflag = thread->perflag[requestedFlags];
     uint32_t size = thisflag.cache.size();
     uint32_t maxmax = (ipv4 ? thisflag.nIPv4 : 0) + (ipv6 ? thisflag.nIPv6 : 0);
     if (max > size) {
         max = size;
     }
     if (max > maxmax) {
         max = maxmax;
     }
     uint32_t i = 0;
     while (i < max) {
         uint32_t j = i + (rand() % (size - i));
         do {
             bool ok = (ipv4 && thisflag.cache[j].v == 4) ||
                       (ipv6 && thisflag.cache[j].v == 6);
             if (ok) {
                 break;
             }
             j++;
             if (j == size) {
                 j = i;
             }
         } while (1);
         addr[i] = thisflag.cache[j];
         thisflag.cache[j] = thisflag.cache[i];
         thisflag.cache[i] = addr[i];
         i++;
     }
     return max;
 }
 
 std::vector<CDnsThread *> dnsThread;
 
 extern "C" void *ThreadDNS(void *arg) {
     CDnsThread *thread = (CDnsThread *)arg;
     thread->run();
     return nullptr;
 }
 
 int StatCompare(const CAddrReport &a, const CAddrReport &b) {
     if (a.uptime[4] == b.uptime[4]) {
         if (a.uptime[3] == b.uptime[3]) {
             return a.clientVersion > b.clientVersion;
         } else {
             return a.uptime[3] > b.uptime[3];
         }
     } else {
         return a.uptime[4] > b.uptime[4];
     }
 }
 
 extern "C" void *ThreadDumper(void *) {
     int count = 0;
     do {
         // First 100s, than 200s, 400s, 800s, 1600s, and then 3200s forever
         Sleep(100000 << count);
         if (count < 5) {
             count++;
         }
 
         {
             std::vector<CAddrReport> v = db.GetAll();
             sort(v.begin(), v.end(), StatCompare);
             FILE *f = fopen("dnsseed.dat.new", "w+");
             if (f) {
                 {
                     CAutoFile cf(f, SER_DISK, CLIENT_VERSION);
                     cf << db;
                 }
                 rename("dnsseed.dat.new", "dnsseed.dat");
             }
             FILE *d = fopen("dnsseed.dump", "w");
             fprintf(d, "# address                                        good  "
                        "lastSuccess    %%(2h)   %%(8h)   %%(1d)   %%(7d)  "
                        "%%(30d)  blocks      svcs  version\n");
             double stat[5] = {0, 0, 0, 0, 0};
             for (CAddrReport rep : v) {
                 fprintf(
                     d,
                     "%-47s  %4d  %11" PRId64
                     "  %6.2f%% %6.2f%% %6.2f%% %6.2f%% %6.2f%%  %6i  %08" PRIx64
                     "  %5i \"%s\"\n",
                     rep.ip.ToString().c_str(), (int)rep.fGood, rep.lastSuccess,
                     100.0 * rep.uptime[0], 100.0 * rep.uptime[1],
                     100.0 * rep.uptime[2], 100.0 * rep.uptime[3],
                     100.0 * rep.uptime[4], rep.blocks, rep.services,
                     rep.clientVersion, rep.clientSubVersion.c_str());
                 stat[0] += rep.uptime[0];
                 stat[1] += rep.uptime[1];
                 stat[2] += rep.uptime[2];
                 stat[3] += rep.uptime[3];
                 stat[4] += rep.uptime[4];
             }
             fclose(d);
             FILE *ff = fopen("dnsstats.log", "a");
             fprintf(ff, "%llu %g %g %g %g %g\n",
                     (unsigned long long)(time(nullptr)), stat[0], stat[1],
                     stat[2], stat[3], stat[4]);
             fclose(ff);
         }
     } while (1);
     return nullptr;
 }
 
 extern "C" void *ThreadStats(void *) {
     bool first = true;
     do {
         char c[256];
         time_t tim = time(nullptr);
         struct tm *tmp = localtime(&tim);
         strftime(c, 256, "[%y-%m-%d %H:%M:%S]", tmp);
         CAddrDbStats stats;
         db.GetStats(stats);
         if (first) {
             first = false;
             printf("\n\n\n\x1b[3A");
         } else
             printf("\x1b[2K\x1b[u");
         printf("\x1b[s");
         uint64_t requests = 0;
         uint64_t queries = 0;
         for (unsigned int i = 0; i < dnsThread.size(); i++) {
             requests += dnsThread[i]->dns_opt.nRequests;
             queries += dnsThread[i]->dbQueries;
         }
         printf("%s %i/%i available (%i tried in %is, %i new, %i active), %i "
                "banned; %llu DNS requests, %llu db queries\n",
                c, stats.nGood, stats.nAvail, stats.nTracked, stats.nAge,
                stats.nNew, stats.nAvail - stats.nTracked - stats.nNew,
                stats.nBanned, (unsigned long long)requests,
                (unsigned long long)queries);
         Sleep(1000);
     } while (1);
     return nullptr;
 }
 
 static const std::string mainnet_seeds[] = {
     "seed.bitcoinabc.org", "seed-abc.bitcoinforks.org", "seed.bitprim.org",
     "seed.deadalnix.me",   "seeder.criptolayer.net",    ""};
 static const std::string testnet_seeds[] = {
     "testnet-seed.bitcoinabc.org",    "testnet-seed-abc.bitcoinforks.org",
     "testnet-seed.bitprim.org",       "testnet-seed.deadalnix.me",
     "testnet-seeder.criptolayer.net", ""};
 static const std::string *seeds = mainnet_seeds;
 
 const static unsigned int MAX_HOSTS_PER_SEED = 128;
 
 extern "C" void *ThreadSeeder(void *) {
     do {
         for (int i = 0; seeds[i] != ""; i++) {
             std::vector<CNetAddr> ips;
             LookupHost(seeds[i].c_str(), ips, MAX_HOSTS_PER_SEED, true);
             for (auto &ip : ips) {
                 db.Add(CAddress(CService(ip, GetDefaultPort()), ServiceFlags()),
                        true);
             }
         }
         Sleep(1800000);
     } while (1);
     return nullptr;
 }
 
 int main(int argc, char **argv) {
     // The logger dump everything on the console by default.
     GetLogger().m_print_to_console = true;
 
     signal(SIGPIPE, SIG_IGN);
     setbuf(stdout, nullptr);
     CDnsSeedOpts opts;
     opts.ParseCommandLine(argc, argv);
     printf("Supporting whitelisted filters: ");
     for (std::set<uint64_t>::const_iterator it = opts.filter_whitelist.begin();
          it != opts.filter_whitelist.end(); it++) {
         if (it != opts.filter_whitelist.begin()) {
             printf(",");
         }
         printf("0x%lx", (unsigned long)*it);
     }
     printf("\n");
     if (opts.tor) {
         CService service(LookupNumeric(opts.tor, 9050));
         if (service.IsValid()) {
             printf("Using Tor proxy at %s\n", service.ToStringIPPort().c_str());
-            SetProxy(NET_TOR, proxyType(service));
+            SetProxy(NET_ONION, proxyType(service));
         }
     }
     if (opts.ipv4_proxy) {
         CService service(LookupNumeric(opts.ipv4_proxy, 9050));
         if (service.IsValid()) {
             printf("Using IPv4 proxy at %s\n",
                    service.ToStringIPPort().c_str());
             SetProxy(NET_IPV4, proxyType(service));
         }
     }
     if (opts.ipv6_proxy) {
         CService service(LookupNumeric(opts.ipv6_proxy, 9050));
         if (service.IsValid()) {
             printf("Using IPv6 proxy at %s\n",
                    service.ToStringIPPort().c_str());
             SetProxy(NET_IPV6, proxyType(service));
         }
     }
     bool fDNS = true;
     if (opts.fUseTestNet) {
         printf("Using testnet.\n");
         netMagic[0] = 0xf4;
         netMagic[1] = 0xe5;
         netMagic[2] = 0xf3;
         netMagic[3] = 0xf4;
         seeds = testnet_seeds;
         fTestNet = true;
     }
     if (!opts.ns) {
         printf("No nameserver set. Not starting DNS server.\n");
         fDNS = false;
     }
     if (fDNS && !opts.host) {
         fprintf(stderr, "No hostname set. Please use -h.\n");
         exit(1);
     }
     if (fDNS && !opts.mbox) {
         fprintf(stderr, "No e-mail address set. Please use -m.\n");
         exit(1);
     }
     FILE *f = fopen("dnsseed.dat", "r");
     if (f) {
         printf("Loading dnsseed.dat...");
         CAutoFile cf(f, SER_DISK, CLIENT_VERSION);
         cf >> db;
         if (opts.fWipeBan) db.banned.clear();
         if (opts.fWipeIgnore) db.ResetIgnores();
         printf("done\n");
     }
     pthread_t threadDns, threadSeed, threadDump, threadStats;
     if (fDNS) {
         printf("Starting %i DNS threads for %s on %s (port %i)...",
                opts.nDnsThreads, opts.host, opts.ns, opts.nPort);
         dnsThread.clear();
         for (int i = 0; i < opts.nDnsThreads; i++) {
             dnsThread.push_back(new CDnsThread(&opts, i));
             pthread_create(&threadDns, nullptr, ThreadDNS, dnsThread[i]);
             printf(".");
             Sleep(20);
         }
         printf("done\n");
     }
     printf("Starting seeder...");
     pthread_create(&threadSeed, nullptr, ThreadSeeder, nullptr);
     printf("done\n");
     printf("Starting %i crawler threads...", opts.nThreads);
     pthread_attr_t attr_crawler;
     pthread_attr_init(&attr_crawler);
     pthread_attr_setstacksize(&attr_crawler, 0x20000);
     for (int i = 0; i < opts.nThreads; i++) {
         pthread_t thread;
         pthread_create(&thread, &attr_crawler, ThreadCrawler, &opts.nThreads);
     }
     pthread_attr_destroy(&attr_crawler);
     printf("done\n");
     pthread_create(&threadStats, nullptr, ThreadStats, nullptr);
     pthread_create(&threadDump, nullptr, ThreadDumper, nullptr);
     void *res;
     pthread_join(threadDump, &res);
     return 0;
 }
diff --git a/src/test/netbase_tests.cpp b/src/test/netbase_tests.cpp
index e273bbc96..d5736080a 100644
--- a/src/test/netbase_tests.cpp
+++ b/src/test/netbase_tests.cpp
@@ -1,337 +1,337 @@
 // Copyright (c) 2012-2016 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include "netbase.h"
 #include "test/test_bitcoin.h"
 #include "utilstrencodings.h"
 
 #include <string>
 
 #include <boost/test/unit_test.hpp>
 
 BOOST_FIXTURE_TEST_SUITE(netbase_tests, BasicTestingSetup)
 
 static CNetAddr ResolveIP(const char *ip) {
     CNetAddr addr;
     LookupHost(ip, addr, false);
     return addr;
 }
 
 static CSubNet ResolveSubNet(const char *subnet) {
     CSubNet ret;
     LookupSubNet(subnet, ret);
     return ret;
 }
 
 static CNetAddr CreateInternal(const char *host) {
     CNetAddr addr;
     addr.SetInternal(host);
     return addr;
 }
 
 BOOST_AUTO_TEST_CASE(netbase_networks) {
     BOOST_CHECK(ResolveIP("127.0.0.1").GetNetwork() == NET_UNROUTABLE);
     BOOST_CHECK(ResolveIP("::1").GetNetwork() == NET_UNROUTABLE);
     BOOST_CHECK(ResolveIP("8.8.8.8").GetNetwork() == NET_IPV4);
     BOOST_CHECK(ResolveIP("2001::8888").GetNetwork() == NET_IPV6);
     BOOST_CHECK(
         ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetNetwork() ==
-        NET_TOR);
+        NET_ONION);
     BOOST_CHECK(CreateInternal("foo.com").GetNetwork() == NET_INTERNAL);
 }
 
 BOOST_AUTO_TEST_CASE(netbase_properties) {
 
     BOOST_CHECK(ResolveIP("127.0.0.1").IsIPv4());
     BOOST_CHECK(ResolveIP("::FFFF:192.168.1.1").IsIPv4());
     BOOST_CHECK(ResolveIP("::1").IsIPv6());
     BOOST_CHECK(ResolveIP("10.0.0.1").IsRFC1918());
     BOOST_CHECK(ResolveIP("192.168.1.1").IsRFC1918());
     BOOST_CHECK(ResolveIP("172.31.255.255").IsRFC1918());
     BOOST_CHECK(ResolveIP("2001:0DB8::").IsRFC3849());
     BOOST_CHECK(ResolveIP("169.254.1.1").IsRFC3927());
     BOOST_CHECK(ResolveIP("2002::1").IsRFC3964());
     BOOST_CHECK(ResolveIP("FC00::").IsRFC4193());
     BOOST_CHECK(ResolveIP("2001::2").IsRFC4380());
     BOOST_CHECK(ResolveIP("2001:10::").IsRFC4843());
     BOOST_CHECK(ResolveIP("FE80::").IsRFC4862());
     BOOST_CHECK(ResolveIP("64:FF9B::").IsRFC6052());
     BOOST_CHECK(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").IsTor());
     BOOST_CHECK(ResolveIP("127.0.0.1").IsLocal());
     BOOST_CHECK(ResolveIP("::1").IsLocal());
     BOOST_CHECK(ResolveIP("8.8.8.8").IsRoutable());
     BOOST_CHECK(ResolveIP("2001::1").IsRoutable());
     BOOST_CHECK(ResolveIP("127.0.0.1").IsValid());
     BOOST_CHECK(
         CreateInternal("FD6B:88C0:8724:edb1:8e4:3588:e546:35ca").IsInternal());
     BOOST_CHECK(CreateInternal("bar.com").IsInternal());
 }
 
 static bool TestSplitHost(std::string test, std::string host, int port) {
     std::string hostOut;
     int portOut = -1;
     SplitHostPort(test, portOut, hostOut);
     return hostOut == host && port == portOut;
 }
 
 BOOST_AUTO_TEST_CASE(netbase_splithost) {
     BOOST_CHECK(TestSplitHost("www.bitcoin.org", "www.bitcoin.org", -1));
     BOOST_CHECK(TestSplitHost("[www.bitcoin.org]", "www.bitcoin.org", -1));
     BOOST_CHECK(TestSplitHost("www.bitcoin.org:80", "www.bitcoin.org", 80));
     BOOST_CHECK(TestSplitHost("[www.bitcoin.org]:80", "www.bitcoin.org", 80));
     BOOST_CHECK(TestSplitHost("127.0.0.1", "127.0.0.1", -1));
     BOOST_CHECK(TestSplitHost("127.0.0.1:8333", "127.0.0.1", 8333));
     BOOST_CHECK(TestSplitHost("[127.0.0.1]", "127.0.0.1", -1));
     BOOST_CHECK(TestSplitHost("[127.0.0.1]:8333", "127.0.0.1", 8333));
     BOOST_CHECK(TestSplitHost("::ffff:127.0.0.1", "::ffff:127.0.0.1", -1));
     BOOST_CHECK(
         TestSplitHost("[::ffff:127.0.0.1]:8333", "::ffff:127.0.0.1", 8333));
     BOOST_CHECK(TestSplitHost("[::]:8333", "::", 8333));
     BOOST_CHECK(TestSplitHost("::8333", "::8333", -1));
     BOOST_CHECK(TestSplitHost(":8333", "", 8333));
     BOOST_CHECK(TestSplitHost("[]:8333", "", 8333));
     BOOST_CHECK(TestSplitHost("", "", -1));
 }
 
 static bool TestParse(std::string src, std::string canon) {
     CService addr(LookupNumeric(src.c_str(), 65535));
     return canon == addr.ToString();
 }
 
 BOOST_AUTO_TEST_CASE(netbase_lookupnumeric) {
     BOOST_CHECK(TestParse("127.0.0.1", "127.0.0.1:65535"));
     BOOST_CHECK(TestParse("127.0.0.1:8333", "127.0.0.1:8333"));
     BOOST_CHECK(TestParse("::ffff:127.0.0.1", "127.0.0.1:65535"));
     BOOST_CHECK(TestParse("::", "[::]:65535"));
     BOOST_CHECK(TestParse("[::]:8333", "[::]:8333"));
     BOOST_CHECK(TestParse("[127.0.0.1]", "127.0.0.1:65535"));
     BOOST_CHECK(TestParse(":::", "[::]:0"));
 
     // verify that an internal address fails to resolve
     BOOST_CHECK(TestParse("[fd6b:88c0:8724:1:2:3:4:5]", "[::]:0"));
     // and that a one-off resolves correctly
     BOOST_CHECK(TestParse("[fd6c:88c0:8724:1:2:3:4:5]",
                           "[fd6c:88c0:8724:1:2:3:4:5]:65535"));
 }
 
 BOOST_AUTO_TEST_CASE(onioncat_test) {
 
     // values from
     // https://web.archive.org/web/20121122003543/http://www.cypherpunk.at/onioncat/wiki/OnionCat
     CNetAddr addr1(ResolveIP("5wyqrzbvrdsumnok.onion"));
     CNetAddr addr2(ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca"));
     BOOST_CHECK(addr1 == addr2);
     BOOST_CHECK(addr1.IsTor());
     BOOST_CHECK(addr1.ToStringIP() == "5wyqrzbvrdsumnok.onion");
     BOOST_CHECK(addr1.IsRoutable());
 }
 
 BOOST_AUTO_TEST_CASE(subnet_test) {
 
     BOOST_CHECK(ResolveSubNet("1.2.3.0/24") ==
                 ResolveSubNet("1.2.3.0/255.255.255.0"));
     BOOST_CHECK(ResolveSubNet("1.2.3.0/24") !=
                 ResolveSubNet("1.2.4.0/255.255.255.0"));
     BOOST_CHECK(ResolveSubNet("1.2.3.0/24").Match(ResolveIP("1.2.3.4")));
     BOOST_CHECK(!ResolveSubNet("1.2.2.0/24").Match(ResolveIP("1.2.3.4")));
     BOOST_CHECK(ResolveSubNet("1.2.3.4").Match(ResolveIP("1.2.3.4")));
     BOOST_CHECK(ResolveSubNet("1.2.3.4/32").Match(ResolveIP("1.2.3.4")));
     BOOST_CHECK(!ResolveSubNet("1.2.3.4").Match(ResolveIP("5.6.7.8")));
     BOOST_CHECK(!ResolveSubNet("1.2.3.4/32").Match(ResolveIP("5.6.7.8")));
     BOOST_CHECK(
         ResolveSubNet("::ffff:127.0.0.1").Match(ResolveIP("127.0.0.1")));
     BOOST_CHECK(
         ResolveSubNet("1:2:3:4:5:6:7:8").Match(ResolveIP("1:2:3:4:5:6:7:8")));
     BOOST_CHECK(
         !ResolveSubNet("1:2:3:4:5:6:7:8").Match(ResolveIP("1:2:3:4:5:6:7:9")));
     BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:0/112")
                     .Match(ResolveIP("1:2:3:4:5:6:7:1234")));
     BOOST_CHECK(
         ResolveSubNet("192.168.0.1/24").Match(ResolveIP("192.168.0.2")));
     BOOST_CHECK(
         ResolveSubNet("192.168.0.20/29").Match(ResolveIP("192.168.0.18")));
     BOOST_CHECK(ResolveSubNet("1.2.2.1/24").Match(ResolveIP("1.2.2.4")));
     BOOST_CHECK(ResolveSubNet("1.2.2.110/31").Match(ResolveIP("1.2.2.111")));
     BOOST_CHECK(ResolveSubNet("1.2.2.20/26").Match(ResolveIP("1.2.2.63")));
     // All-Matching IPv6 Matches arbitrary IPv4 and IPv6
     BOOST_CHECK(ResolveSubNet("::/0").Match(ResolveIP("1:2:3:4:5:6:7:1234")));
     BOOST_CHECK(ResolveSubNet("::/0").Match(ResolveIP("1.2.3.4")));
     // All-Matching IPv4 does not Match IPv6
     BOOST_CHECK(
         !ResolveSubNet("0.0.0.0/0").Match(ResolveIP("1:2:3:4:5:6:7:1234")));
     // Invalid subnets Match nothing (not even invalid addresses)
     BOOST_CHECK(!CSubNet().Match(ResolveIP("1.2.3.4")));
     BOOST_CHECK(!ResolveSubNet("").Match(ResolveIP("4.5.6.7")));
     BOOST_CHECK(!ResolveSubNet("bloop").Match(ResolveIP("0.0.0.0")));
     BOOST_CHECK(!ResolveSubNet("bloop").Match(ResolveIP("hab")));
     // Check valid/invalid
     BOOST_CHECK(ResolveSubNet("1.2.3.0/0").IsValid());
     BOOST_CHECK(!ResolveSubNet("1.2.3.0/-1").IsValid());
     BOOST_CHECK(ResolveSubNet("1.2.3.0/32").IsValid());
     BOOST_CHECK(!ResolveSubNet("1.2.3.0/33").IsValid());
     BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8/0").IsValid());
     BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8/33").IsValid());
     BOOST_CHECK(!ResolveSubNet("1:2:3:4:5:6:7:8/-1").IsValid());
     BOOST_CHECK(ResolveSubNet("1:2:3:4:5:6:7:8/128").IsValid());
     BOOST_CHECK(!ResolveSubNet("1:2:3:4:5:6:7:8/129").IsValid());
     BOOST_CHECK(!ResolveSubNet("fuzzy").IsValid());
 
     // CNetAddr constructor test
     BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).IsValid());
     BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).Match(ResolveIP("127.0.0.1")));
     BOOST_CHECK(!CSubNet(ResolveIP("127.0.0.1")).Match(ResolveIP("127.0.0.2")));
     BOOST_CHECK(CSubNet(ResolveIP("127.0.0.1")).ToString() == "127.0.0.1/32");
 
     CSubNet subnet = CSubNet(ResolveIP("1.2.3.4"), 32);
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32");
     subnet = CSubNet(ResolveIP("1.2.3.4"), 8);
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8");
     subnet = CSubNet(ResolveIP("1.2.3.4"), 0);
     BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0");
 
     subnet = CSubNet(ResolveIP("1.2.3.4"), ResolveIP("255.255.255.255"));
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32");
     subnet = CSubNet(ResolveIP("1.2.3.4"), ResolveIP("255.0.0.0"));
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8");
     subnet = CSubNet(ResolveIP("1.2.3.4"), ResolveIP("0.0.0.0"));
     BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0");
 
     BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).IsValid());
     BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8"))
                     .Match(ResolveIP("1:2:3:4:5:6:7:8")));
     BOOST_CHECK(!CSubNet(ResolveIP("1:2:3:4:5:6:7:8"))
                      .Match(ResolveIP("1:2:3:4:5:6:7:9")));
     BOOST_CHECK(CSubNet(ResolveIP("1:2:3:4:5:6:7:8")).ToString() ==
                 "1:2:3:4:5:6:7:8/128");
 
     subnet = ResolveSubNet("1.2.3.4/255.255.255.255");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/32");
     subnet = ResolveSubNet("1.2.3.4/255.255.255.254");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/31");
     subnet = ResolveSubNet("1.2.3.4/255.255.255.252");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.4/30");
     subnet = ResolveSubNet("1.2.3.4/255.255.255.248");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/29");
     subnet = ResolveSubNet("1.2.3.4/255.255.255.240");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/28");
     subnet = ResolveSubNet("1.2.3.4/255.255.255.224");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/27");
     subnet = ResolveSubNet("1.2.3.4/255.255.255.192");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/26");
     subnet = ResolveSubNet("1.2.3.4/255.255.255.128");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/25");
     subnet = ResolveSubNet("1.2.3.4/255.255.255.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.3.0/24");
     subnet = ResolveSubNet("1.2.3.4/255.255.254.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.2.0/23");
     subnet = ResolveSubNet("1.2.3.4/255.255.252.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/22");
     subnet = ResolveSubNet("1.2.3.4/255.255.248.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/21");
     subnet = ResolveSubNet("1.2.3.4/255.255.240.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/20");
     subnet = ResolveSubNet("1.2.3.4/255.255.224.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/19");
     subnet = ResolveSubNet("1.2.3.4/255.255.192.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/18");
     subnet = ResolveSubNet("1.2.3.4/255.255.128.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/17");
     subnet = ResolveSubNet("1.2.3.4/255.255.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/16");
     subnet = ResolveSubNet("1.2.3.4/255.254.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/15");
     subnet = ResolveSubNet("1.2.3.4/255.252.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/14");
     subnet = ResolveSubNet("1.2.3.4/255.248.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/13");
     subnet = ResolveSubNet("1.2.3.4/255.240.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/12");
     subnet = ResolveSubNet("1.2.3.4/255.224.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/11");
     subnet = ResolveSubNet("1.2.3.4/255.192.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/10");
     subnet = ResolveSubNet("1.2.3.4/255.128.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/9");
     subnet = ResolveSubNet("1.2.3.4/255.0.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.0.0.0/8");
     subnet = ResolveSubNet("1.2.3.4/254.0.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/7");
     subnet = ResolveSubNet("1.2.3.4/252.0.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/6");
     subnet = ResolveSubNet("1.2.3.4/248.0.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/5");
     subnet = ResolveSubNet("1.2.3.4/240.0.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/4");
     subnet = ResolveSubNet("1.2.3.4/224.0.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/3");
     subnet = ResolveSubNet("1.2.3.4/192.0.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/2");
     subnet = ResolveSubNet("1.2.3.4/128.0.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/1");
     subnet = ResolveSubNet("1.2.3.4/0.0.0.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "0.0.0.0/0");
 
     subnet = ResolveSubNet(
         "1:2:3:4:5:6:7:8/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1:2:3:4:5:6:7:8/128");
     subnet = ResolveSubNet(
         "1:2:3:4:5:6:7:8/ffff:0000:0000:0000:0000:0000:0000:0000");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1::/16");
     subnet = ResolveSubNet(
         "1:2:3:4:5:6:7:8/0000:0000:0000:0000:0000:0000:0000:0000");
     BOOST_CHECK_EQUAL(subnet.ToString(), "::/0");
     subnet = ResolveSubNet("1.2.3.4/255.255.232.0");
     BOOST_CHECK_EQUAL(subnet.ToString(), "1.2.0.0/255.255.232.0");
     subnet = ResolveSubNet(
         "1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f");
     BOOST_CHECK_EQUAL(
         subnet.ToString(),
         "1:2:3:4:5:6:7:8/ffff:ffff:ffff:fffe:ffff:ffff:ffff:ff0f");
 }
 
 BOOST_AUTO_TEST_CASE(netbase_getgroup) {
     typedef std::vector<uint8_t> Vec8;
     // Local -> !Routable()
     BOOST_CHECK(ResolveIP("127.0.0.1").GetGroup() == Vec8{0});
     // !Valid -> !Routable()
     BOOST_CHECK(ResolveIP("257.0.0.1").GetGroup() == Vec8{0});
     // RFC1918 -> !Routable()
     BOOST_CHECK(ResolveIP("10.0.0.1").GetGroup() == Vec8{0});
     // RFC3927 -> !Routable()
     BOOST_CHECK(ResolveIP("169.254.1.1").GetGroup() == Vec8{0});
     // IPv4
     BOOST_CHECK(ResolveIP("1.2.3.4").GetGroup() == Vec8({NET_IPV4, 1, 2}));
     // RFC6145
     BOOST_CHECK(ResolveIP("::FFFF:0:102:304").GetGroup() ==
                 Vec8({NET_IPV4, 1, 2}));
     // RFC6052
     BOOST_CHECK(ResolveIP("64:FF9B::102:304").GetGroup() ==
                 Vec8({NET_IPV4, 1, 2}));
     // RFC3964
     BOOST_CHECK(ResolveIP("2002:102:304:9999:9999:9999:9999:9999").GetGroup() ==
                 Vec8({NET_IPV4, 1, 2}));
     // RFC4380
     BOOST_CHECK(ResolveIP("2001:0:9999:9999:9999:9999:FEFD:FCFB").GetGroup() ==
                 Vec8({NET_IPV4, 1, 2}));
     // Tor
     BOOST_CHECK(
         ResolveIP("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca").GetGroup() ==
-        Vec8({NET_TOR, 239}));
+        Vec8({NET_ONION, 239}));
     // he.net
     BOOST_CHECK(
         ResolveIP("2001:470:abcd:9999:9999:9999:9999:9999").GetGroup() ==
         Vec8({NET_IPV6, 32, 1, 4, 112, 175}));
     // IPv6
     BOOST_CHECK(
         ResolveIP("2001:2001:9999:9999:9999:9999:9999:9999").GetGroup() ==
         Vec8({NET_IPV6, 32, 1, 32, 1}));
 
     // baz.net sha256 hash:
     // 12929400eb4607c4ac075f087167e75286b179c693eb059a01774b864e8fe505
     Vec8 internal_group = {NET_INTERNAL, 0x12, 0x92, 0x94, 0x00, 0xeb,
                            0x46,         0x07, 0xc4, 0xac, 0x07};
     BOOST_CHECK(CreateInternal("baz.net").GetGroup() == internal_group);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp
index 21af26236..1116082d6 100644
--- a/src/torcontrol.cpp
+++ b/src/torcontrol.cpp
@@ -1,813 +1,813 @@
 // Copyright (c) 2015-2016 The Bitcoin Core developers
 // Distributed under the MIT software license, see the accompanying
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include "torcontrol.h"
 #include "crypto/hmac_sha256.h"
 #include "net.h"
 #include "netbase.h"
 #include "util.h"
 #include "utilstrencodings.h"
 
 #include <cstdlib>
 #include <deque>
 #include <set>
 #include <vector>
 
 #include <boost/algorithm/string/classification.hpp>
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/algorithm/string/split.hpp>
 #include <boost/bind.hpp>
 #include <boost/signals2/signal.hpp>
 
 #include <event2/buffer.h>
 #include <event2/bufferevent.h>
 #include <event2/event.h>
 #include <event2/thread.h>
 #include <event2/util.h>
 
 /** Default control port */
 const std::string DEFAULT_TOR_CONTROL = "127.0.0.1:9051";
 /** Tor cookie size (from control-spec.txt) */
 static const int TOR_COOKIE_SIZE = 32;
 /** Size of client/server nonce for SAFECOOKIE */
 static const int TOR_NONCE_SIZE = 32;
 /** For computing serverHash in SAFECOOKIE */
 static const std::string TOR_SAFE_SERVERKEY =
     "Tor safe cookie authentication server-to-controller hash";
 /** For computing clientHash in SAFECOOKIE */
 static const std::string TOR_SAFE_CLIENTKEY =
     "Tor safe cookie authentication controller-to-server hash";
 /** Exponential backoff configuration - initial timeout in seconds */
 static const float RECONNECT_TIMEOUT_START = 1.0;
 /** Exponential backoff configuration - growth factor */
 static const float RECONNECT_TIMEOUT_EXP = 1.5;
 /**
  * Maximum length for lines received on TorControlConnection.
  * tor-control-spec.txt mentions that there is explicitly no limit defined to
  * line length, this is belt-and-suspenders sanity limit to prevent memory
  * exhaustion.
  */
 static const int MAX_LINE_LENGTH = 100000;
 
 /****** Low-level TorControlConnection ********/
 
 /** Reply from Tor, can be single or multi-line */
 class TorControlReply {
 public:
     TorControlReply() { Clear(); }
 
     int code;
     std::vector<std::string> lines;
 
     void Clear() {
         code = 0;
         lines.clear();
     }
 };
 
 /**
  * Low-level handling for Tor control connection.
  * Speaks the SMTP-like protocol as defined in torspec/control-spec.txt
  */
 class TorControlConnection {
 public:
     typedef std::function<void(TorControlConnection &)> ConnectionCB;
     typedef std::function<void(TorControlConnection &, const TorControlReply &)>
         ReplyHandlerCB;
 
     /** Create a new TorControlConnection.
      */
     explicit TorControlConnection(struct event_base *base);
     ~TorControlConnection();
 
     /**
      * Connect to a Tor control port.
      * target is address of the form host:port.
      * connected is the handler that is called when connection is successfully
      * established.
      * disconnected is a handler that is called when the connection is broken.
      * Return true on success.
      */
     bool Connect(const std::string &target, const ConnectionCB &connected,
                  const ConnectionCB &disconnected);
 
     /**
      * Disconnect from Tor control port.
      */
     bool Disconnect();
 
     /**
      * Send a command, register a handler for the reply.
      * A trailing CRLF is automatically added.
      * Return true on success.
      */
     bool Command(const std::string &cmd, const ReplyHandlerCB &reply_handler);
 
     /** Response handlers for async replies */
     boost::signals2::signal<void(TorControlConnection &,
                                  const TorControlReply &)>
         async_handler;
 
 private:
     /** Callback when ready for use */
     std::function<void(TorControlConnection &)> connected;
     /** Callback when connection lost */
     std::function<void(TorControlConnection &)> disconnected;
     /** Libevent event base */
     struct event_base *base;
     /** Connection to control socket */
     struct bufferevent *b_conn;
     /** Message being received */
     TorControlReply message;
     /** Response handlers */
     std::deque<ReplyHandlerCB> reply_handlers;
 
     /** Libevent handlers: internal */
     static void readcb(struct bufferevent *bev, void *ctx);
     static void eventcb(struct bufferevent *bev, short what, void *ctx);
 };
 
 TorControlConnection::TorControlConnection(struct event_base *_base)
     : base(_base), b_conn(nullptr) {}
 
 TorControlConnection::~TorControlConnection() {
     if (b_conn) {
         bufferevent_free(b_conn);
     }
 }
 
 void TorControlConnection::readcb(struct bufferevent *bev, void *ctx) {
     TorControlConnection *self = static_cast<TorControlConnection *>(ctx);
     struct evbuffer *input = bufferevent_get_input(bev);
     size_t n_read_out = 0;
     char *line;
     assert(input);
     // If there is not a whole line to read, evbuffer_readln returns nullptr
     while ((line = evbuffer_readln(input, &n_read_out, EVBUFFER_EOL_CRLF)) !=
            nullptr) {
         std::string s(line, n_read_out);
         free(line);
         // Short line
         if (s.size() < 4) {
             continue;
         }
         // <status>(-|+| )<data><CRLF>
         self->message.code = atoi(s.substr(0, 3));
         self->message.lines.push_back(s.substr(4));
         // '-','+' or ' '
         char ch = s[3];
         if (ch == ' ') {
             // Final line, dispatch reply and clean up
             if (self->message.code >= 600) {
                 // Dispatch async notifications to async handler.
                 // Synchronous and asynchronous messages are never interleaved
                 self->async_handler(*self, self->message);
             } else {
                 if (!self->reply_handlers.empty()) {
                     // Invoke reply handler with message
                     self->reply_handlers.front()(*self, self->message);
                     self->reply_handlers.pop_front();
                 } else {
                     LogPrint(BCLog::TOR,
                              "tor: Received unexpected sync reply %i\n",
                              self->message.code);
                 }
             }
             self->message.Clear();
         }
     }
 
     // Check for size of buffer - protect against memory exhaustion with very
     // long lines. Do this after evbuffer_readln to make sure all full lines
     // have been removed from the buffer. Everything left is an incomplete line.
     if (evbuffer_get_length(input) > MAX_LINE_LENGTH) {
         LogPrintf("tor: Disconnecting because MAX_LINE_LENGTH exceeded\n");
         self->Disconnect();
     }
 }
 
 void TorControlConnection::eventcb(struct bufferevent *bev, short what,
                                    void *ctx) {
     TorControlConnection *self = static_cast<TorControlConnection *>(ctx);
     if (what & BEV_EVENT_CONNECTED) {
         LogPrint(BCLog::TOR, "tor: Successfully connected!\n");
         self->connected(*self);
     } else if (what & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) {
         if (what & BEV_EVENT_ERROR) {
             LogPrint(BCLog::TOR,
                      "tor: Error connecting to Tor control socket\n");
         } else {
             LogPrint(BCLog::TOR, "tor: End of stream\n");
         }
         self->Disconnect();
         self->disconnected(*self);
     }
 }
 
 bool TorControlConnection::Connect(const std::string &target,
                                    const ConnectionCB &_connected,
                                    const ConnectionCB &_disconnected) {
     if (b_conn) {
         Disconnect();
     }
     // Parse target address:port
     struct sockaddr_storage connect_to_addr;
     int connect_to_addrlen = sizeof(connect_to_addr);
     if (evutil_parse_sockaddr_port(target.c_str(),
                                    (struct sockaddr *)&connect_to_addr,
                                    &connect_to_addrlen) < 0) {
         LogPrintf("tor: Error parsing socket address %s\n", target);
         return false;
     }
 
     // Create a new socket, set up callbacks and enable notification bits
     b_conn = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
     if (!b_conn) {
         return false;
     }
     bufferevent_setcb(b_conn, TorControlConnection::readcb, nullptr,
                       TorControlConnection::eventcb, this);
     bufferevent_enable(b_conn, EV_READ | EV_WRITE);
     this->connected = _connected;
     this->disconnected = _disconnected;
 
     // Finally, connect to target
     if (bufferevent_socket_connect(b_conn, (struct sockaddr *)&connect_to_addr,
                                    connect_to_addrlen) < 0) {
         LogPrintf("tor: Error connecting to address %s\n", target);
         return false;
     }
     return true;
 }
 
 bool TorControlConnection::Disconnect() {
     if (b_conn) {
         bufferevent_free(b_conn);
     }
     b_conn = nullptr;
     return true;
 }
 
 bool TorControlConnection::Command(const std::string &cmd,
                                    const ReplyHandlerCB &reply_handler) {
     if (!b_conn) {
         return false;
     }
     struct evbuffer *buf = bufferevent_get_output(b_conn);
     if (!buf) {
         return false;
     }
     evbuffer_add(buf, cmd.data(), cmd.size());
     evbuffer_add(buf, "\r\n", 2);
     reply_handlers.push_back(reply_handler);
     return true;
 }
 
 /****** General parsing utilities ********/
 
 /* Split reply line in the form 'AUTH METHODS=...' into a type
  * 'AUTH' and arguments 'METHODS=...'.
  */
 static std::pair<std::string, std::string>
 SplitTorReplyLine(const std::string &s) {
     size_t ptr = 0;
     std::string type;
     while (ptr < s.size() && s[ptr] != ' ') {
         type.push_back(s[ptr]);
         ++ptr;
     }
     if (ptr < s.size()) {
         // skip ' '
         ++ptr;
     }
     return make_pair(type, s.substr(ptr));
 }
 
 /**
  * Parse reply arguments in the form 'METHODS=COOKIE,SAFECOOKIE
  * COOKIEFILE=".../control_auth_cookie"'.
  */
 static std::map<std::string, std::string>
 ParseTorReplyMapping(const std::string &s) {
     std::map<std::string, std::string> mapping;
     size_t ptr = 0;
     while (ptr < s.size()) {
         std::string key, value;
         while (ptr < s.size() && s[ptr] != '=') {
             key.push_back(s[ptr]);
             ++ptr;
         }
         // unexpected end of line
         if (ptr == s.size()) {
             return std::map<std::string, std::string>();
         }
         // skip '='
         ++ptr;
         // Quoted string
         if (ptr < s.size() && s[ptr] == '"') {
             // skip '='
             ++ptr;
             bool escape_next = false;
             while (ptr < s.size() && (!escape_next && s[ptr] != '"')) {
                 escape_next = (s[ptr] == '\\');
                 value.push_back(s[ptr]);
                 ++ptr;
             }
             // unexpected end of line
             if (ptr == s.size()) {
                 return std::map<std::string, std::string>();
             }
             // skip closing '"'
             ++ptr;
             /* TODO: unescape value - according to the spec this depends on the
              * context, some strings use C-LogPrintf style escape codes, some
              * don't. So may be better handled at the call site.
              */
         } else {
             // Unquoted value. Note that values can contain '=' at will, just no
             // spaces
             while (ptr < s.size() && s[ptr] != ' ') {
                 value.push_back(s[ptr]);
                 ++ptr;
             }
         }
         if (ptr < s.size() && s[ptr] == ' ') {
             // skip ' ' after key=value
             ++ptr;
         }
         mapping[key] = value;
     }
     return mapping;
 }
 
 /**
  * Read full contents of a file and return them in a std::string.
  * Returns a pair <status, string>.
  * If an error occurred, status will be false, otherwise status will be true and
  * the data will be returned in string.
  *
  * @param maxsize Puts a maximum size limit on the file that is read. If the
  * file is larger than this, truncated data
  *         (with len > maxsize) will be returned.
  */
 static std::pair<bool, std::string>
 ReadBinaryFile(const fs::path &filename,
                size_t maxsize = std::numeric_limits<size_t>::max()) {
     FILE *f = fsbridge::fopen(filename, "rb");
     if (f == nullptr) {
         return std::make_pair(false, "");
     }
     std::string retval;
     char buffer[128];
     size_t n;
     while ((n = fread(buffer, 1, sizeof(buffer), f)) > 0) {
         retval.append(buffer, buffer + n);
         if (retval.size() > maxsize) {
             break;
         }
     }
     fclose(f);
     return std::make_pair(true, retval);
 }
 
 /**
  * Write contents of std::string to a file.
  * @return true on success.
  */
 static bool WriteBinaryFile(const fs::path &filename, const std::string &data) {
     FILE *f = fsbridge::fopen(filename, "wb");
     if (f == nullptr) {
         return false;
     }
     if (fwrite(data.data(), 1, data.size(), f) != data.size()) {
         fclose(f);
         return false;
     }
     fclose(f);
     return true;
 }
 
 /****** Bitcoin specific TorController implementation ********/
 
 /**
  * Controller that connects to Tor control socket, authenticate, then create
  * and maintain a ephemeral hidden service.
  */
 class TorController {
 public:
     TorController(struct event_base *base, const std::string &target);
     ~TorController();
 
     /** Get name fo file to store private key in */
     fs::path GetPrivateKeyFile();
 
     /** Reconnect, after getting disconnected */
     void Reconnect();
 
 private:
     struct event_base *base;
     std::string target;
     TorControlConnection conn;
     std::string private_key;
     std::string service_id;
     bool reconnect;
     struct event *reconnect_ev;
     float reconnect_timeout;
     CService service;
     /** Cookie for SAFECOOKIE auth */
     std::vector<uint8_t> cookie;
     /** ClientNonce for SAFECOOKIE auth */
     std::vector<uint8_t> clientNonce;
 
     /** Callback for ADD_ONION result */
     void add_onion_cb(TorControlConnection &conn, const TorControlReply &reply);
     /** Callback for AUTHENTICATE result */
     void auth_cb(TorControlConnection &conn, const TorControlReply &reply);
     /** Callback for AUTHCHALLENGE result */
     void authchallenge_cb(TorControlConnection &conn,
                           const TorControlReply &reply);
     /** Callback for PROTOCOLINFO result */
     void protocolinfo_cb(TorControlConnection &conn,
                          const TorControlReply &reply);
     /** Callback after successful connection */
     void connected_cb(TorControlConnection &conn);
     /** Callback after connection lost or failed connection attempt */
     void disconnected_cb(TorControlConnection &conn);
 
     /** Callback for reconnect timer */
     static void reconnect_cb(evutil_socket_t fd, short what, void *arg);
 };
 
 TorController::TorController(struct event_base *_base,
                              const std::string &_target)
     : base(_base), target(_target), conn(base), reconnect(true),
       reconnect_ev(0), reconnect_timeout(RECONNECT_TIMEOUT_START) {
     reconnect_ev = event_new(base, -1, 0, reconnect_cb, this);
     if (!reconnect_ev) {
         LogPrintf(
             "tor: Failed to create event for reconnection: out of memory?\n");
     }
     // Start connection attempts immediately
     if (!conn.Connect(_target,
                       boost::bind(&TorController::connected_cb, this, _1),
                       boost::bind(&TorController::disconnected_cb, this, _1))) {
         LogPrintf("tor: Initiating connection to Tor control port %s failed\n",
                   _target);
     }
     // Read service private key if cached
     std::pair<bool, std::string> pkf = ReadBinaryFile(GetPrivateKeyFile());
     if (pkf.first) {
         LogPrint(BCLog::TOR, "tor: Reading cached private key from %s\n",
                  GetPrivateKeyFile());
         private_key = pkf.second;
     }
 }
 
 TorController::~TorController() {
     if (reconnect_ev) {
         event_free(reconnect_ev);
         reconnect_ev = nullptr;
     }
     if (service.IsValid()) {
         RemoveLocal(service);
     }
 }
 
 void TorController::add_onion_cb(TorControlConnection &_conn,
                                  const TorControlReply &reply) {
     if (reply.code == 250) {
         LogPrint(BCLog::TOR, "tor: ADD_ONION successful\n");
         for (const std::string &s : reply.lines) {
             std::map<std::string, std::string> m = ParseTorReplyMapping(s);
             std::map<std::string, std::string>::iterator i;
             if ((i = m.find("ServiceID")) != m.end()) {
                 service_id = i->second;
             }
             if ((i = m.find("PrivateKey")) != m.end()) {
                 private_key = i->second;
             }
         }
         service = LookupNumeric(std::string(service_id + ".onion").c_str(),
                                 GetListenPort());
         LogPrintf("tor: Got service ID %s, advertising service %s\n",
                   service_id, service.ToString());
         if (WriteBinaryFile(GetPrivateKeyFile(), private_key)) {
             LogPrint(BCLog::TOR, "tor: Cached service private key to %s\n",
                      GetPrivateKeyFile());
         } else {
             LogPrintf("tor: Error writing service private key to %s\n",
                       GetPrivateKeyFile());
         }
         AddLocal(service, LOCAL_MANUAL);
         // ... onion requested - keep connection open
     } else if (reply.code == 510) { // 510 Unrecognized command
         LogPrintf("tor: Add onion failed with unrecognized command (You "
                   "probably need to upgrade Tor)\n");
     } else {
         LogPrintf("tor: Add onion failed; error code %d\n", reply.code);
     }
 }
 
 void TorController::auth_cb(TorControlConnection &_conn,
                             const TorControlReply &reply) {
     if (reply.code == 250) {
         LogPrint(BCLog::TOR, "tor: Authentication successful\n");
 
         // Now that we know Tor is running setup the proxy for onion addresses
         // if -onion isn't set to something else.
         if (gArgs.GetArg("-onion", "") == "") {
             CService resolved(LookupNumeric("127.0.0.1", 9050));
             proxyType addrOnion = proxyType(resolved, true);
-            SetProxy(NET_TOR, addrOnion);
-            SetLimited(NET_TOR, false);
+            SetProxy(NET_ONION, addrOnion);
+            SetLimited(NET_ONION, false);
         }
 
         // Finally - now create the service
         // No private key, generate one
         if (private_key.empty()) {
             // Explicitly request RSA1024 - see issue #9214
             private_key = "NEW:RSA1024";
         }
         // Request hidden service, redirect port.
         // Note that the 'virtual' port doesn't have to be the same as our
         // internal port, but this is just a convenient choice. TODO; refactor
         // the shutdown sequence some day.
         _conn.Command(strprintf("ADD_ONION %s Port=%i,127.0.0.1:%i",
                                 private_key, GetListenPort(), GetListenPort()),
                       boost::bind(&TorController::add_onion_cb, this, _1, _2));
     } else {
         LogPrintf("tor: Authentication failed\n");
     }
 }
 
 /** Compute Tor SAFECOOKIE response.
  *
  *    ServerHash is computed as:
  *      HMAC-SHA256("Tor safe cookie authentication server-to-controller hash",
  *                  CookieString | ClientNonce | ServerNonce)
  *    (with the HMAC key as its first argument)
  *
  *    After a controller sends a successful AUTHCHALLENGE command, the
  *    next command sent on the connection must be an AUTHENTICATE command,
  *    and the only authentication string which that AUTHENTICATE command
  *    will accept is:
  *
  *      HMAC-SHA256("Tor safe cookie authentication controller-to-server hash",
  *                  CookieString | ClientNonce | ServerNonce)
  *
  */
 static std::vector<uint8_t>
 ComputeResponse(const std::string &key, const std::vector<uint8_t> &cookie,
                 const std::vector<uint8_t> &clientNonce,
                 const std::vector<uint8_t> &serverNonce) {
     CHMAC_SHA256 computeHash((const uint8_t *)key.data(), key.size());
     std::vector<uint8_t> computedHash(CHMAC_SHA256::OUTPUT_SIZE, 0);
     computeHash.Write(cookie.data(), cookie.size());
     computeHash.Write(clientNonce.data(), clientNonce.size());
     computeHash.Write(serverNonce.data(), serverNonce.size());
     computeHash.Finalize(computedHash.data());
     return computedHash;
 }
 
 void TorController::authchallenge_cb(TorControlConnection &_conn,
                                      const TorControlReply &reply) {
     if (reply.code == 250) {
         LogPrint(BCLog::TOR,
                  "tor: SAFECOOKIE authentication challenge successful\n");
         std::pair<std::string, std::string> l =
             SplitTorReplyLine(reply.lines[0]);
         if (l.first == "AUTHCHALLENGE") {
             std::map<std::string, std::string> m =
                 ParseTorReplyMapping(l.second);
             std::vector<uint8_t> serverHash = ParseHex(m["SERVERHASH"]);
             std::vector<uint8_t> serverNonce = ParseHex(m["SERVERNONCE"]);
             LogPrint(BCLog::TOR,
                      "tor: AUTHCHALLENGE ServerHash %s ServerNonce %s\n",
                      HexStr(serverHash), HexStr(serverNonce));
             if (serverNonce.size() != 32) {
                 LogPrintf(
                     "tor: ServerNonce is not 32 bytes, as required by spec\n");
                 return;
             }
 
             std::vector<uint8_t> computedServerHash = ComputeResponse(
                 TOR_SAFE_SERVERKEY, cookie, clientNonce, serverNonce);
             if (computedServerHash != serverHash) {
                 LogPrintf("tor: ServerHash %s does not match expected "
                           "ServerHash %s\n",
                           HexStr(serverHash), HexStr(computedServerHash));
                 return;
             }
 
             std::vector<uint8_t> computedClientHash = ComputeResponse(
                 TOR_SAFE_CLIENTKEY, cookie, clientNonce, serverNonce);
             _conn.Command("AUTHENTICATE " + HexStr(computedClientHash),
                           boost::bind(&TorController::auth_cb, this, _1, _2));
         } else {
             LogPrintf("tor: Invalid reply to AUTHCHALLENGE\n");
         }
     } else {
         LogPrintf("tor: SAFECOOKIE authentication challenge failed\n");
     }
 }
 
 void TorController::protocolinfo_cb(TorControlConnection &_conn,
                                     const TorControlReply &reply) {
     if (reply.code == 250) {
         std::set<std::string> methods;
         std::string cookiefile;
         /*
          * 250-AUTH METHODS=COOKIE,SAFECOOKIE
          * COOKIEFILE="/home/x/.tor/control_auth_cookie"
          * 250-AUTH METHODS=NULL
          * 250-AUTH METHODS=HASHEDPASSWORD
          */
         for (const std::string &s : reply.lines) {
             std::pair<std::string, std::string> l = SplitTorReplyLine(s);
             if (l.first == "AUTH") {
                 std::map<std::string, std::string> m =
                     ParseTorReplyMapping(l.second);
                 std::map<std::string, std::string>::iterator i;
                 if ((i = m.find("METHODS")) != m.end()) {
                     boost::split(methods, i->second, boost::is_any_of(","));
                 }
                 if ((i = m.find("COOKIEFILE")) != m.end()) {
                     cookiefile = i->second;
                 }
             } else if (l.first == "VERSION") {
                 std::map<std::string, std::string> m =
                     ParseTorReplyMapping(l.second);
                 std::map<std::string, std::string>::iterator i;
                 if ((i = m.find("Tor")) != m.end()) {
                     LogPrint(BCLog::TOR, "tor: Connected to Tor version %s\n",
                              i->second);
                 }
             }
         }
         for (const std::string &s : methods) {
             LogPrint(BCLog::TOR, "tor: Supported authentication method: %s\n",
                      s);
         }
         // Prefer NULL, otherwise SAFECOOKIE. If a password is provided, use
         // HASHEDPASSWORD
         /* Authentication:
          *   cookie:   hex-encoded ~/.tor/control_auth_cookie
          *   password: "password"
          */
         std::string torpassword = gArgs.GetArg("-torpassword", "");
         if (!torpassword.empty()) {
             if (methods.count("HASHEDPASSWORD")) {
                 LogPrint(BCLog::TOR,
                          "tor: Using HASHEDPASSWORD authentication\n");
                 boost::replace_all(torpassword, "\"", "\\\"");
                 _conn.Command(
                     "AUTHENTICATE \"" + torpassword + "\"",
                     boost::bind(&TorController::auth_cb, this, _1, _2));
             } else {
                 LogPrintf("tor: Password provided with -torpassword, but "
                           "HASHEDPASSWORD authentication is not available\n");
             }
         } else if (methods.count("NULL")) {
             LogPrint(BCLog::TOR, "tor: Using NULL authentication\n");
             _conn.Command("AUTHENTICATE",
                           boost::bind(&TorController::auth_cb, this, _1, _2));
         } else if (methods.count("SAFECOOKIE")) {
             // Cookie: hexdump -e '32/1 "%02x""\n"'  ~/.tor/control_auth_cookie
             LogPrint(BCLog::TOR,
                      "tor: Using SAFECOOKIE authentication, "
                      "reading cookie authentication from %s\n",
                      cookiefile);
             std::pair<bool, std::string> status_cookie =
                 ReadBinaryFile(cookiefile, TOR_COOKIE_SIZE);
             if (status_cookie.first &&
                 status_cookie.second.size() == TOR_COOKIE_SIZE) {
                 // _conn.Command("AUTHENTICATE " + HexStr(status_cookie.second),
                 // boost::bind(&TorController::auth_cb, this, _1, _2));
                 cookie = std::vector<uint8_t>(status_cookie.second.begin(),
                                               status_cookie.second.end());
                 clientNonce = std::vector<uint8_t>(TOR_NONCE_SIZE, 0);
                 GetRandBytes(&clientNonce[0], TOR_NONCE_SIZE);
                 _conn.Command("AUTHCHALLENGE SAFECOOKIE " + HexStr(clientNonce),
                               boost::bind(&TorController::authchallenge_cb,
                                           this, _1, _2));
             } else {
                 if (status_cookie.first) {
                     LogPrintf("tor: Authentication cookie %s is not exactly %i "
                               "bytes, as is required by the spec\n",
                               cookiefile, TOR_COOKIE_SIZE);
                 } else {
                     LogPrintf("tor: Authentication cookie %s could not be "
                               "opened (check permissions)\n",
                               cookiefile);
                 }
             }
         } else if (methods.count("HASHEDPASSWORD")) {
             LogPrintf("tor: The only supported authentication mechanism left "
                       "is password, but no password provided with "
                       "-torpassword\n");
         } else {
             LogPrintf("tor: No supported authentication method\n");
         }
     } else {
         LogPrintf("tor: Requesting protocol info failed\n");
     }
 }
 
 void TorController::connected_cb(TorControlConnection &_conn) {
     reconnect_timeout = RECONNECT_TIMEOUT_START;
     // First send a PROTOCOLINFO command to figure out what authentication is
     // expected
     if (!_conn.Command(
             "PROTOCOLINFO 1",
             boost::bind(&TorController::protocolinfo_cb, this, _1, _2))) {
         LogPrintf("tor: Error sending initial protocolinfo command\n");
     }
 }
 
 void TorController::disconnected_cb(TorControlConnection &_conn) {
     // Stop advertising service when disconnected
     if (service.IsValid()) {
         RemoveLocal(service);
     }
     service = CService();
     if (!reconnect) {
         return;
     }
 
     LogPrint(BCLog::TOR,
              "tor: Not connected to Tor control port %s, trying to reconnect\n",
              target);
 
     // Single-shot timer for reconnect. Use exponential backoff.
     struct timeval time = MillisToTimeval(int64_t(reconnect_timeout * 1000.0));
     if (reconnect_ev) {
         event_add(reconnect_ev, &time);
     }
     reconnect_timeout *= RECONNECT_TIMEOUT_EXP;
 }
 
 void TorController::Reconnect() {
     /* Try to reconnect and reestablish if we get booted - for example, Tor may
      * be restarting.
      */
     if (!conn.Connect(target,
                       boost::bind(&TorController::connected_cb, this, _1),
                       boost::bind(&TorController::disconnected_cb, this, _1))) {
         LogPrintf(
             "tor: Re-initiating connection to Tor control port %s failed\n",
             target);
     }
 }
 
 fs::path TorController::GetPrivateKeyFile() {
     return GetDataDir() / "onion_private_key";
 }
 
 void TorController::reconnect_cb(evutil_socket_t fd, short what, void *arg) {
     TorController *self = static_cast<TorController *>(arg);
     self->Reconnect();
 }
 
 /****** Thread ********/
 static struct event_base *gBase;
 static std::thread torControlThread;
 
 static void TorControlThread() {
     TorController ctrl(gBase, gArgs.GetArg("-torcontrol", DEFAULT_TOR_CONTROL));
 
     event_base_dispatch(gBase);
 }
 
 void StartTorControl() {
     assert(!gBase);
 #ifdef WIN32
     evthread_use_windows_threads();
 #else
     evthread_use_pthreads();
 #endif
     gBase = event_base_new();
     if (!gBase) {
         LogPrintf("tor: Unable to create event_base\n");
         return;
     }
 
     torControlThread = std::thread(
         std::bind(&TraceThread<void (*)()>, "torcontrol", &TorControlThread));
 }
 
 void InterruptTorControl() {
     if (gBase) {
         LogPrintf("tor: Thread interrupt\n");
         event_base_loopbreak(gBase);
     }
 }
 
 void StopTorControl() {
     if (gBase) {
         torControlThread.join();
         event_base_free(gBase);
         gBase = nullptr;
     }
 }