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

Code before:
        if (args.IsArgSet("-dnsseed") && args.GetBoolArg("-dnsseed", DEFAULT_DNSSEED) && args.IsArgSet("-proxy")) {
            LogInfo("-dnsseed is ignored when -connect is used and -proxy is specified");
        }
    }

    const std::string& i2psam_arg = args.GetArg("-i2psam", "");
    if (!i2psam_arg.empty()) {
        const std::optional<CService> addr{Lookup(i2psam_arg, 7656, fNameLookup)};
        if (!addr.has_value() || !addr->IsValid()) {
            return InitError(strprintf(_("Invalid -i2psam address or hostname: '%s'"), i2psam_arg));
        }
        SetProxy(NET_I2P, Proxy{addr.value()});
    } else {
        if (!onlynets.empty() && g_reachable_nets.Contains(NET_I2P)) {
            return InitError(
                _("Outbound connections restricted to i2p (-onlynet=i2p) but "
                  "-i2psam is not provided"));
        }
        g_reachable_nets.Remove(NET_I2P);
    }

    connOptions.m_i2p_accept_incoming = args.GetBoolArg("-i2pacceptincoming", DEFAULT_I2P_ACCEPT_INCOMING);

    if (auto conflict = CheckBindingConflicts(connOptions)) {
        return InitError(Untranslated(strprintf("Duplicate binding configuration for address %s. "
            "Please check your -bind, -whitebind, and onion binding settings.",
            conflict->ToStringAddrPort())));
    }

    if (!node.connman->Start(scheduler, connOptions)) {
        return false;
    }

    // ********************************************************* Step 13: finished

    // At this point, the RPC is "started", but still in warmup, which means it
    // cannot yet be called. Before we make it callable, we need to make sure
    // that the RPC's view of the best block is valid and consistent with
    // ChainstateManager's active tip.
    SetRPCWarmupFinished();

    uiInterface.InitMessage(_("Done loading"));

    for (const auto& client : node.chain_clients) {
        client->start(scheduler);
    }

    BanMan* banman = node.banman.get();
    scheduler.scheduleEvery([banman]{
        banman->DumpBanlist();
    }, DUMP_BANS_INTERVAL);

Review comment (suggestion):
Here and also in the commit message, this lists 3 categories: `-bind`, `-whitebind`, `onion`. There is an `-onion` config option which is not related to binding. This could be confusing. The intention here is to mean "onion" -> "a subset of -bind if suffixed with =onion". That is, just mentioning `-bind` also covers `-bind=...=onion`. So maybe change this to:

`Please check your -bind and -whitebind settings` or to
`Please check your -bind, -bind=...=onion and -whitebind settings`.

Code after:
        if (args.IsArgSet("-dnsseed") && args.GetBoolArg("-dnsseed", DEFAULT_DNSSEED) && args.IsArgSet("-proxy")) {
            LogInfo("-dnsseed is ignored when -connect is used and -proxy is specified");
        }
    }

    const std::string& i2psam_arg = args.GetArg("-i2psam", "");
    if (!i2psam_arg.empty()) {
        const std::optional<CService> addr{Lookup(i2psam_arg, 7656, fNameLookup)};
        if (!addr.has_value() || !addr->IsValid()) {
            return InitError(strprintf(_("Invalid -i2psam address or hostname: '%s'"), i2psam_arg));
        }
        SetProxy(NET_I2P, Proxy{addr.value()});
    } else {
        if (!onlynets.empty() && g_reachable_nets.Contains(NET_I2P)) {
            return InitError(
                _("Outbound connections restricted to i2p (-onlynet=i2p) but "
                  "-i2psam is not provided"));
        }
        g_reachable_nets.Remove(NET_I2P);
    }

    connOptions.m_i2p_accept_incoming = args.GetBoolArg("-i2pacceptincoming", DEFAULT_I2P_ACCEPT_INCOMING);

    if (auto conflict = CheckBindingConflicts(connOptions)) {
        return InitError(strprintf(
            _("Duplicate binding configuration for address %s. "
                "Please check your -bind, -bind=...=onion and -whitebind settings."),
                    conflict->ToStringAddrPort()));
    }

    if (!node.connman->Start(scheduler, connOptions)) {
        return false;
    }

    // ********************************************************* Step 13: finished

    // At this point, the RPC is "started", but still in warmup, which means it
    // cannot yet be called. Before we make it callable, we need to make sure
    // that the RPC's view of the best block is valid and consistent with
    // ChainstateManager's active tip.
    SetRPCWarmupFinished();

    uiInterface.InitMessage(_("Done loading"));

    for (const auto& client : node.chain_clients) {
        client->start(scheduler);
    }

    BanMan* banman = node.banman.get();
    scheduler.scheduleEvery([banman]{
        banman->DumpBanlist();