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]{

Review comment (refactor):
Is it expected that I'm seeing this twice?
```
2025-08-26T18:23:45Z [error] Duplicate binding configuration for address 127.0.0.1:11012. Please check your -bind, -whitebind, and onion binding settings.
2025-08-26T18:23:45Z tor: Thread interrupt
2025-08-26T18:23:45Z torcontrol thread exit
2025-08-26T18:23:45Z Shutdown in progress...
Error: Duplicate binding configuration for address 127.0.0.1:11012. Please check your -bind, -whitebind, and onion binding settings.
```

And if we're not actually stopping the execution, shouldn't it rather be a warning?

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();