Repository: bitcoin/bitcoin
File: src/init.cpp (C++)

Code before:
    CTxMemPool::Options mempool_opts{
        .check_ratio = chainparams.DefaultConsistencyChecks() ? 1 : 0,
        .signals = &validation_signals,
    };
    auto result{ApplyArgsManOptions(args, chainparams, mempool_opts)};
    if (!result) {
        return InitError(util::ErrorString(result));
    }

    bool do_reindex{args.GetBoolArg("-reindex", false)};
    const bool do_reindex_chainstate{args.GetBoolArg("-reindex-chainstate", false)};

    for (bool fLoaded = false; !fLoaded && !ShutdownRequested(node);) {
        bilingual_str mempool_error;
        node.mempool = std::make_unique<CTxMemPool>(mempool_opts, mempool_error);
        if (!mempool_error.empty()) {
            return InitError(mempool_error);
        }
        LogPrintf("* Using %.1f MiB for in-memory UTXO set (plus up to %.1f MiB of unused mempool space)\n", cache_sizes.coins * (1.0 / 1024 / 1024), mempool_opts.max_size_bytes * (1.0 / 1024 / 1024));

        blockman_opts.wipe_block_tree_db = do_reindex;

        try {
            node.chainman = std::make_unique<ChainstateManager>(*Assert(node.shutdown), chainman_opts, blockman_opts);
        } catch (dbwrapper_error&) {
            return InitError(Untranslated("Error opening block database."));
        } catch (std::exception& e) {
            return InitError(strprintf(Untranslated("Failed to initialize ChainstateManager: %s"), e.what()));
        }
        ChainstateManager& chainman = *node.chainman;

        // This is defined and set here instead of inline in validation.h to avoid a hard
        // dependency between validation and index/base, since the latter is not in
        // libbitcoinkernel.
        chainman.snapshot_download_completed = [&node]() {
            if (!node.chainman->m_blockman.IsPruneMode()) {
                LogPrintf("[snapshot] re-enabling NODE_NETWORK services\n");
                node.connman->AddLocalServices(NODE_NETWORK);
            }

            LogPrintf("[snapshot] restarting indexes\n");

            // Drain the validation interface queue to ensure that the old indexes
            // don't have any pending work.
            Assert(node.validation_signals)->SyncWithValidationInterfaceQueue();

            for (auto* index : node.indexes) {
                index->Interrupt();
                index->Stop();
                if (!(index->Init() && index->StartBackgroundSync())) {
                    LogPrintf("[snapshot] WARNING failed to restart index %s on snapshot chain\n", index->GetName());

Review comment (bug):
Might be premature at this stage, but in theory we could be opening both the block database and txdb at this stage. I haven't looked at `dbwrapper_error` yet so not sure if this is possible, but perhaps we could bubble up the actual db name that failed to open instead of assuming it's always the block database?

Code after:
        SetProxy(NET_IPV4, addrProxy);
        SetProxy(NET_IPV6, addrProxy);
        SetProxy(NET_CJDNS, addrProxy);
        SetNameProxy(addrProxy);
        onion_proxy = addrProxy;
    }

    const bool onlynet_used_with_onion{args.IsArgSet("-onlynet") && g_reachable_nets.Contains(NET_ONION)};

    // -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 = args.GetArg("-onion", "");
    if (onionArg != "") {
        if (onionArg == "0") { // Handle -noonion/-onion=0
            onion_proxy = Proxy{};
            if (onlynet_used_with_onion) {
                return InitError(
                    _("Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "
                      "reaching the Tor network is explicitly forbidden: -onion=0"));
            }
        } else {
            if (IsUnixSocketPath(onionArg)) {
                onion_proxy = Proxy(onionArg, proxyRandomize);
            } else {
                const std::optional<CService> addr{Lookup(onionArg, 9050, fNameLookup)};
                if (!addr.has_value() || !addr->IsValid()) {
                    return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg));
                }

                onion_proxy = Proxy(addr.value(), proxyRandomize);
            }
        }
    }

    if (onion_proxy.IsValid()) {
        SetProxy(NET_ONION, onion_proxy);
    } else {
        // If -listenonion is set, then we will (try to) connect to the Tor control port
        // later from the torcontrol thread and may retrieve the onion proxy from there.
        const bool listenonion_disabled{!args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)};
        if (onlynet_used_with_onion && listenonion_disabled) {
            return InitError(
                _("Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "
                  "reaching the Tor network is not provided: none of -proxy, -onion or "
                  "-listenonion is given"));
        }
        g_reachable_nets.Remove(NET_ONION);
    }

    for (const std::string& strAddr : args.GetArgs("-externalip")) {