Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
2251for (const std::string& strBind : args.GetArgs("-whitebind")) {2252NetWhitebindPermissions whitebind;2253bilingual_str error;2254if (!NetWhitebindPermissions::TryParse(strBind, whitebind, error)) return InitError(error);2255connOptions.vWhiteBinds.push_back(whitebind);2256}2258// If the user did not specify -bind= or -whitebind= then we bind2259// on any address - 0.0.0.0 (IPv4) and :: (IPv6).2260connOptions.bind_on_any = args.GetArgs("-bind").empty() && args.GetArgs("-whitebind").empty();2262// Emit a warning if a bad port is given to -port= but only if -bind and -whitebind are not2263// given, because if they are, then -port= is ignored.2264if (connOptions.bind_on_any && args.IsArgSet("-port")) {2265const uint16_t port_arg = args.GetIntArg("-port", 0);2266if (IsBadPort(port_arg)) {2267InitWarning(BadPortWarning("-port", port_arg));2268}2269}2271CService onion_service_target;2272if (!connOptions.onion_binds.empty()) {2273onion_service_target = connOptions.onion_binds.front();2274} else if (!connOptions.vBinds.empty()) {2275onion_service_target = connOptions.vBinds.front();2276} else {2277onion_service_target = DefaultOnionServiceTarget(default_bind_port_onion);2278connOptions.onion_binds.push_back(onion_service_target);2279}2281if (listenonion) {2282if (connOptions.onion_binds.size() > 1) {2283InitWarning(strprintf(_("More than one onion bind address is provided. Using %s "2284"for the automatically created Tor onion service."),2285onion_service_target.ToStringAddrPort()));2286}2287node.tor_controller = std::make_unique<TorController>(gArgs.GetArg("-torcontrol", DEFAULT_TOR_CONTROL), onion_service_target);2288}2290bool should_discover = connOptions.bind_on_any;2291if (!should_discover) {2292for (const auto& bind : connOptions.vBinds) {2293if (bind.IsBindAny()) {2294should_discover = true;2295break;2296}2297}2298}2300if (!should_discover) {2301for (const auto& whitebind : connOptions.vWhiteBinds) {2302if (whitebind.m_service.IsBindAny()) {2303should_discover = true;2304break;2305}2306}2307}2309if (should_discover) {2310// Only add all IP addresses of the machine if we would be listening on2311// any address - 0.0.0.0 (IPv4) and :: (IPv6).2312Discover();2313}2315for (const auto& net : args.GetArgs("-whitelist")) {2316NetWhitelistPermissions subnet;2317ConnectionDirection connection_direction;2318bilingual_str error;2319if (!NetWhitelistPermissions::TryParse(net, subnet, connection_direction, error)) return InitError(error);2320if (connection_direction & ConnectionDirection::In) {2321connOptions.vWhitelistedRangeIncoming.push_back(subnet);2322}2323if (connection_direction & ConnectionDirection::Out) {2324connOptions.vWhitelistedRangeOutgoing.push_back(subnet);2325}2326}2328connOptions.vSeedNodes = args.GetArgs("-seednode");2330const auto connect = args.GetArgs("-connect");2331if (!connect.empty() || args.IsArgNegated("-connect")) {2332// Do not initiate other outgoing connections when connecting to trusted2333// nodes, or when -noconnect is specified.2334connOptions.m_use_addrman_outgoing = false;2336if (connect.size() != 1 || connect[0] != "0") {2337connOptions.m_specified_outgoing = connect;2338}2339if (!connOptions.m_specified_outgoing.empty() && !connOptions.vSeedNodes.empty()) {2340LogInfo("-seednode is ignored when -connect is used");2341}2343if (args.IsArgSet("-dnsseed") && args.GetBoolArg("-dnsseed", DEFAULT_DNSSEED) && args.IsArgSet("-proxy")) {2344LogInfo("-dnsseed is ignored when -connect is used and -proxy is specified");2345}2346}2348const std::string& i2psam_arg = args.GetArg("-i2psam", "");2349if (!i2psam_arg.empty()) {2350const std::optional<CService> addr{Lookup(i2psam_arg, 7656, fNameLookup)};2351if (!addr.has_value() || !addr->IsValid()) {2352return InitError(strprintf(_("Invalid -i2psam address or hostname: '%s'"), i2psam_arg));2353}2354SetProxy(NET_I2P, Proxy{addr.value()});2355} else {2356if (!onlynets.empty() && g_reachable_nets.Contains(NET_I2P)) {2357return InitError(2358_("Outbound connections restricted to i2p (-onlynet=i2p) but "2359"-i2psam is not provided"));2360}2361g_reachable_nets.Remove(NET_I2P);2362}2364connOptions.m_i2p_accept_incoming = args.GetBoolArg("-i2pacceptincoming", DEFAULT_I2P_ACCEPT_INCOMING);2366if (auto conflict = CheckBindingConflicts(connOptions)) {2367return InitError(strprintf(2368_("Duplicate binding configuration for address %s. "2369"Please check your -bind, -bind=...=onion and -whitebind settings."),2370conflict->ToStringAddrPort()));2371}2373if (args.GetBoolArg("-privatebroadcast", DEFAULT_PRIVATE_BROADCAST)) {2374// If -listenonion is set, then NET_ONION may not be reachable now2375// but may become reachable later, thus only error here if it is not2376// reachable and will not become reachable for sure.2377const bool onion_may_become_reachable{listenonion && (!args.IsArgSet("-onlynet") || onlynet_used_with_onion)};2378if (!g_reachable_nets.Contains(NET_I2P) &&2379!g_reachable_nets.Contains(NET_ONION) &&2380!onion_may_become_reachable) {2381return InitError(_("Private broadcast of own transactions requested (-privatebroadcast), "2382"but none of Tor or I2P networks is reachable"));2383}2384if (!connOptions.m_use_addrman_outgoing) {2385return InitError(_("Private broadcast of own transactions requested (-privatebroadcast), "2386"but -connect is also configured. They are incompatible because the "2387"private broadcast needs to open new connections to randomly "2388"chosen Tor or I2P peers. Consider using -maxconnections=0 -addnode=... "2389"instead"));2390}2391if (!proxyRandomize && (g_reachable_nets.Contains(NET_ONION) || onion_may_become_reachable)) {2392InitWarning(_("Private broadcast of own transactions requested (-privatebroadcast) and "2393"-proxyrandomize is disabled. Tor circuits for private broadcast connections "2394"may be correlated to other connections over Tor. To reduce this risk, set "2395"-proxyrandomize=1."));2396}2397}2399if (!node.connman->Start(scheduler, connOptions)) {2400return false;2401}2403// ********************************************************* Step 13: finished2405// At this point, the RPC is "started", but still in warmup, which means it2406// cannot yet be called. Before we make it callable, we need to make sure2407// that the RPC's view of the best block is valid and consistent with2408// ChainstateManager's active tip.2409SetRPCWarmupFinished();2411uiInterface.InitMessage(_("Done loading"));2413for (const auto& client : node.chain_clients) {2414client->start(scheduler);2415}2417BanMan* banman = node.banman.get();2418scheduler.scheduleEvery([banman]{2419banman->DumpBanlist();2420}, DUMP_BANS_INTERVAL);2422if (node.peerman) node.peerman->StartScheduledTasks(scheduler);2424#if HAVE_SYSTEM2425StartupNotify(args);2426#endif2428return true;2429}2431bool StartIndexBackgroundSync(NodeContext& node)2432{2433ChainstateManager& chainman = *Assert(node.chainman);2434const Chainstate& chainstate = WITH_LOCK(::cs_main, return chainman.ValidatedChainstate());2435const CChain& index_chain = chainstate.m_chain;2436const int current_height = WITH_LOCK(::cs_main, return index_chain.Height());2438// Skip checking data availability if we have not synced any blocks yet2439if (current_height > 0) {2440// Before starting index sync, verify that all required block data is available2441// on disk from each index's current sync position up to the chain tip.2442//2443// This is done separately for undo and block data: First we verify block + undo2444// data existence from tip down to the lowest height required by any index that2445// needs undo data (e.g., coinstatsindex, blockfilterindex). Then, if any2446// block-only index needs to sync from a lower height than previously covered,2447// verify block data existence down to that lower height.2448//2449// This avoids checking undo data for blocks where no index requires it,2450// though currently block and undo data availability are synchronized on disk2451// under normal circumstances.2452std::optional<const CBlockIndex*> block_start;2453std::string block_start_name;2454std::optional<const CBlockIndex*> undo_start;2455std::string undo_start_name;2457for (const auto& index : node.indexes) {2458const IndexSummary& summary = index->GetSummary();2459if (summary.synced) continue;2461// Get the last common block between the index best block and the active chain2462const CBlockIndex* pindex = nullptr;2463{2464LOCK(::cs_main);2465pindex = chainman.m_blockman.LookupBlockIndex(summary.best_block_hash);2466if (!pindex) {2467LogWarning("Failed to find block manager entry for best block %s from %s, falling back to genesis for index sync",2468summary.best_block_hash.ToString(), summary.name);2469} else if (!index_chain.Contains(*pindex)) {2470pindex = index_chain.FindFork(*pindex);2471}2472}2473if (!pindex) {2474pindex = index_chain.Genesis();2475}2477bool need_undo = index->CustomOptions().connect_undo_data;2478auto& op_start_index = need_undo ? undo_start : block_start;2479auto& name_index = need_undo ? undo_start_name : block_start_name;2481if (op_start_index && pindex->nHeight >= op_start_index.value()->nHeight) continue;2482op_start_index = pindex;2483name_index = summary.name;2484}2486// Verify all blocks needed to sync to current tip are present including undo data.2487if (undo_start) {2488LOCK(::cs_main);2489if (!chainman.m_blockman.CheckBlockDataAvailability(*index_chain.Tip(), *Assert(undo_start.value()), BlockStatus{BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO})) {2490return InitError(Untranslated(strprintf("%s best block of the index goes beyond pruned data (including undo data). Please disable the index or reindex (which will download the whole blockchain again)", undo_start_name)));2491}2492}2494// Verify all blocks needed to sync to current tip are present unless we already checked all of them above.2495if (block_start && !(undo_start && undo_start.value()->nHeight <= block_start.value()->nHeight)) {2496LOCK(::cs_main);2497if (!chainman.m_blockman.CheckBlockDataAvailability(*index_chain.Tip(), *Assert(block_start.value()), BlockStatus{BLOCK_HAVE_DATA})) {2498return InitError(Untranslated(strprintf("%s best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)", block_start_name)));2499}2500}