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

Code before:
            [&seen](const CService& service) {
                return !seen.insert(service).second;  // Remove if already seen
            });
        vBinds.erase(it, vBinds.end());
    }

    // Step 3: Simple deduplication for onion_binds
    {
        std::set<CService> seen;
        auto it = std::remove_if(onion_binds.begin(), onion_binds.end(),
            [&seen](const CService& service) {
                return !seen.insert(service).second;  // Remove if already seen
            });
        onion_binds.erase(it, onion_binds.end());
    }

    // Step 4: Check for cross-vector conflicts
    // Build sets for efficient lookup
    std::set<CService> whitebind_services;
    for (const auto& wb : vWhiteBinds) {
        whitebind_services.insert(wb.m_service);
    }

    // Check if any service from vBinds exists in vWhiteBinds
    for (const auto& bind : vBinds) {
        if (whitebind_services.count(bind)) {
            return bind;  // Conflict between vBinds and vWhiteBinds
        }
    }

    // Check if any service from onion_binds exists in vWhiteBinds or vBinds
    std::set<CService> bind_services(vBinds.begin(), vBinds.end());
    for (const auto& onion_bind : onion_binds) {
        if (whitebind_services.count(onion_bind)) {
            return onion_bind;  // Conflict between onion_binds and vWhiteBinds
        }
        if (bind_services.count(onion_bind)) {
            return onion_bind;  // Conflict between onion_binds and vBinds
        }
    }

    return std::nullopt;  // No conflicts found
}

// A GUI user may opt to retry once with do_reindex set if there is a failure during chainstate initialization.
// The function therefore has to support re-entry.
static ChainstateLoadResult InitAndLoadChainstate(
    NodeContext& node,
    bool do_reindex,
    const bool do_reindex_chainstate,
    const kernel::CacheSizes& cache_sizes,

Review comment (suggestion):
nit:
```suggestion
        if (whitebind_services.contains(bind)) {
```

Code after:
    node.notifications.reset(); // Drop state, such as a cached tip block
    node.mempool.reset();
    node.chainman.reset(); // Drop state, such as an initialized m_block_tree_db

    const CChainParams& chainparams = Params();

    Assert(!node.notifications); // Was reset above
    node.notifications = std::make_unique<KernelNotifications>(Assert(node.shutdown_request), node.exit_status, *Assert(node.warnings));
    ReadNotificationArgs(args, *node.notifications);

    CTxMemPool::Options mempool_opts{
        .check_ratio = chainparams.DefaultConsistencyChecks() ? 1 : 0,
        .signals = node.validation_signals.get(),
    };
    Assert(ApplyArgsManOptions(args, chainparams, mempool_opts)); // no error can happen, already checked in AppInitParameterInteraction
    bilingual_str mempool_error;
    Assert(!node.mempool); // Was reset above
    node.mempool = std::make_unique<CTxMemPool>(mempool_opts, mempool_error);
    if (!mempool_error.empty()) {
        return {ChainstateLoadStatus::FAILURE_FATAL, mempool_error};
    }
    LogInfo("* Using %.1f MiB for in-memory UTXO set (plus up to %.1f MiB of unused mempool space)",
            cache_sizes.coins * (1.0 / 1024 / 1024),
            mempool_opts.max_size_bytes * (1.0 / 1024 / 1024));
    ChainstateManager::Options chainman_opts{
        .chainparams = chainparams,
        .datadir = args.GetDataDirNet(),
        .notifications = *node.notifications,
        .signals = node.validation_signals.get(),
    };
    Assert(ApplyArgsManOptions(args, chainman_opts)); // no error can happen, already checked in AppInitParameterInteraction

    BlockManager::Options blockman_opts{
        .chainparams = chainman_opts.chainparams,
        .blocks_dir = args.GetBlocksDirPath(),
        .notifications = chainman_opts.notifications,
        .block_tree_db_params = DBParams{
            .path = args.GetDataDirNet() / "blocks" / "index",
            .cache_bytes = cache_sizes.block_tree_db,
            .wipe_data = do_reindex,
        },
    };
    Assert(ApplyArgsManOptions(args, blockman_opts)); // no error can happen, already checked in AppInitParameterInteraction

    // Creating the chainstate manager internally creates a BlockManager, opens
    // the blocks tree db, and wipes existing block files in case of a reindex.
    // The coinsdb is opened at a later point on LoadChainstate.
    Assert(!node.chainman); // Was reset above
    try {
        node.chainman = std::make_unique<ChainstateManager>(*Assert(node.shutdown_signal), chainman_opts, blockman_opts);
    } catch (dbwrapper_error& e) {