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.
1751// Check for host lookup allowed before parsing any network related parameters1752fNameLookup = args.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP);1754bool proxyRandomize = args.GetBoolArg("-proxyrandomize", DEFAULT_PROXYRANDOMIZE);1755// -proxy sets a proxy for outgoing network traffic, possibly per network.1756// -noproxy, -proxy=0 or -proxy="" can be used to remove the proxy setting, this is the default1757Proxy ipv4_proxy;1758Proxy ipv6_proxy;1759Proxy onion_proxy;1760Proxy name_proxy;1761Proxy cjdns_proxy;1762for (const std::string& param_value : args.GetArgs("-proxy")) {1763const auto eq_pos{param_value.rfind('=')};1764const std::string proxy_str{param_value.substr(0, eq_pos)}; // e.g. 127.0.0.1:9050=ipv4 -> 127.0.0.1:90501765std::string net_str;1766if (eq_pos != std::string::npos) {1767if (eq_pos + 1 == param_value.length()) {1768return InitError(strprintf(_("Invalid -proxy address or hostname, ends with '=': '%s'"), param_value));1769}1770net_str = param_value.substr(eq_pos + 1); // e.g. 127.0.0.1:9050=ipv4 -> ipv41771}1773Proxy proxy;1774if (!proxy_str.empty() && proxy_str != "0") {1775if (IsUnixSocketPath(proxy_str)) {1776proxy = Proxy{proxy_str, /*tor_stream_isolation=*/proxyRandomize};1777} else {1778const std::optional<CService> addr{Lookup(proxy_str, DEFAULT_TOR_SOCKS_PORT, fNameLookup)};1779if (!addr.has_value()) {1780return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxy_str));1781}1782proxy = Proxy{addr.value(), /*tor_stream_isolation=*/proxyRandomize};1783}1784if (!proxy.IsValid()) {1785return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxy_str));1786}1787}1789if (net_str.empty()) { // For all networks.1790ipv4_proxy = ipv6_proxy = name_proxy = cjdns_proxy = onion_proxy = proxy;1791} else {1792switch (ParseNetwork(net_str)) {1793case NET_IPV4: ipv4_proxy = name_proxy = proxy; break;1794case NET_IPV6: ipv6_proxy = name_proxy = proxy; break;1795case NET_ONION: onion_proxy = proxy; break;1796case NET_CJDNS: cjdns_proxy = proxy; break;1797case NET_UNROUTABLE:1798case NET_I2P:1799case NET_INTERNAL:1800case NET_MAX:1801return InitError(strprintf(_("Unrecognized network in -proxy='%s': '%s'"), param_value, net_str));1802} // no default case, so the compiler can warn about missing cases1803}1804}1805if (ipv4_proxy.IsValid()) {1806SetProxy(NET_IPV4, ipv4_proxy);1807}1808if (ipv6_proxy.IsValid()) {1809SetProxy(NET_IPV6, ipv6_proxy);1810}1811if (name_proxy.IsValid()) {1812SetNameProxy(name_proxy);1813}1814if (cjdns_proxy.IsValid()) {1815SetProxy(NET_CJDNS, cjdns_proxy);1816}1818const bool onlynet_used_with_onion{!onlynets.empty() && g_reachable_nets.Contains(NET_ONION)};1820// -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses1821// -noonion (or -onion=0) disables connecting to .onion entirely1822// An empty string is used to not override the onion proxy (in which case it defaults to -proxy set above, or none)1823std::string onionArg = args.GetArg("-onion", "");1824if (onionArg != "") {1825if (onionArg == "0") { // Handle -noonion/-onion=01826onion_proxy = Proxy{};1827if (onlynet_used_with_onion) {1828return InitError(1829_("Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "1830"reaching the Tor network is explicitly forbidden: -onion=0"));1831}1832} else {1833if (IsUnixSocketPath(onionArg)) {1834onion_proxy = Proxy(onionArg, /*tor_stream_isolation=*/proxyRandomize);1835} else {1836const std::optional<CService> addr{Lookup(onionArg, DEFAULT_TOR_SOCKS_PORT, fNameLookup)};1837if (!addr.has_value() || !addr->IsValid()) {1838return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg));1839}1841onion_proxy = Proxy(addr.value(), /*tor_stream_isolation=*/proxyRandomize);1842}1843}1844}1846const bool listenonion{args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)};1847if (onion_proxy.IsValid()) {1848SetProxy(NET_ONION, onion_proxy);1849} else {1850// If -listenonion is set, then we will (try to) connect to the Tor control port1851// later from the torcontrol thread and may retrieve the onion proxy from there.1852if (onlynet_used_with_onion && !listenonion) {1853return InitError(1854_("Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "1855"reaching the Tor network is not provided: none of -proxy, -onion or "1856"-listenonion is given"));1857}1858g_reachable_nets.Remove(NET_ONION);1859}1861for (const std::string& strAddr : args.GetArgs("-externalip")) {1862const std::optional<CService> addrLocal{Lookup(strAddr, GetListenPort(), fNameLookup)};1863if (addrLocal.has_value() && addrLocal->IsValid())1864AddLocal(addrLocal.value(), LOCAL_MANUAL, /*add_even_if_unreachable=*/true);1865else1866return InitError(ResolveErrMsg("externalip", strAddr));1867}1869#ifdef ENABLE_ZMQ1870g_zmq_notification_interface = CZMQNotificationInterface::Create(1871[&chainman = node.chainman](std::vector<std::byte>& block, const CBlockIndex& index) {1872assert(chainman);1873if (auto ret{chainman->m_blockman.ReadRawBlock(WITH_LOCK(cs_main, return index.GetBlockPos()))}) {1874block = std::move(*ret);1875return true;1876}1877return false;1878});1880if (g_zmq_notification_interface) {1881validation_signals.RegisterValidationInterface(g_zmq_notification_interface.get());1882}1883#endif1885// ********************************************************* Step 7: load block chain1887// cache size calculations1888node::LogOversizedDbCache(args);1889const auto [index_cache_sizes, kernel_cache_sizes] = CalculateCacheSizes(args, g_enabled_filter_types.size());1891LogInfo("Cache configuration:");1892LogInfo("* Using %.1f MiB for block index database", kernel_cache_sizes.block_tree_db / double(1_MiB));1893if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {1894LogInfo("* Using %.1f MiB for transaction index database", index_cache_sizes.tx_index / double(1_MiB));1895}1896if (args.GetBoolArg("-txospenderindex", DEFAULT_TXOSPENDERINDEX)) {1897LogInfo("* Using %.1f MiB for transaction output spender index database", index_cache_sizes.txospender_index / double(1_MiB));1898}1899for (BlockFilterType filter_type : g_enabled_filter_types) {1900LogInfo("* Using %.1f MiB for %s block filter index database",1901index_cache_sizes.filter_index / double(1_MiB), BlockFilterTypeName(filter_type));1902}1903LogInfo("* Using %.1f MiB for chain state database", kernel_cache_sizes.coins_db / double(1_MiB));1905assert(!node.mempool);1906assert(!node.chainman);1908bool do_reindex{args.GetBoolArg("-reindex", false)};1909const bool do_reindex_chainstate{args.GetBoolArg("-reindex-chainstate", false)};1911// Chainstate initialization and loading may be retried once with reindexing by GUI users1912auto [status, error] = InitAndLoadChainstate(1913node,1914do_reindex,1915do_reindex_chainstate,1916kernel_cache_sizes,1917args);1918if (status == ChainstateLoadStatus::FAILURE && !do_reindex && !ShutdownRequested(node)) {1919// suggest a reindex1920bool do_retry{HasTestOption(args, "reindex_after_failure_noninteractive_yes") ||1921uiInterface.ThreadSafeQuestion(1922error + Untranslated(".\n\n") + _("Do you want to rebuild the databases now?"),1923error.original + ".\nPlease restart with -reindex or -reindex-chainstate to recover.",1924CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT)};1925if (!do_retry) {1926return false;1927}1928do_reindex = true;1929if (!Assert(node.shutdown_signal)->reset()) {1930LogError("Internal error: failed to reset shutdown signal.\n");1931}1932std::tie(status, error) = InitAndLoadChainstate(1933node,1934do_reindex,1935do_reindex_chainstate,1936kernel_cache_sizes,1937args);1938}1939if (status != ChainstateLoadStatus::SUCCESS && status != ChainstateLoadStatus::INTERRUPTED) {1940return InitError(error);1941}1943// As LoadBlockIndex can take several minutes, it's possible the user1944// requested to kill the GUI during the last operation. If so, exit.1945if (ShutdownRequested(node)) {1946LogInfo("Shutdown requested. Exiting.");1947return true;1948}1950ChainstateManager& chainman = *Assert(node.chainman);1952assert(!node.fee_estimator_man);1953// Don't initialize fee estimation with old data if we don't relay transactions,1954// as they would never get updated.1955if (!peerman_opts.ignore_incoming_txs) {1956bool read_stale_estimates = args.GetBoolArg("-acceptstalefeeestimates", DEFAULT_ACCEPT_STALE_FEE_ESTIMATES);1957if (read_stale_estimates && (chainparams.GetChainType() != ChainType::REGTEST)) {1958return InitError(strprintf(_("acceptstalefeeestimates is not supported on %s chain."), chainparams.GetChainTypeString()));1959}1960MaybeMigrateLegacyFeeEstimates(args);1961node.fee_estimator_man = std::make_unique<FeeRateEstimatorManager>(BlockPolicyFeeEstPath(args), read_stale_estimates, MempoolPolicyEstimatorPath(args), *Assert(node.mempool), chainman);1963// Flush estimates to disk periodically1964FeeRateEstimatorManager* fee_estimator_man = node.fee_estimator_man.get();1965scheduler.scheduleEvery([fee_estimator_man] { fee_estimator_man->IntervalFlush(); }, FEE_FLUSH_INTERVAL);1966validation_signals.RegisterValidationInterface(fee_estimator_man);1967}1969auto& kernel_notifications{*Assert(node.notifications)};1971assert(!node.peerman);1972node.peerman = PeerManager::make(*node.connman, *node.addrman,1973node.banman.get(), chainman,1974*node.mempool, *node.warnings,1975peerman_opts);1976validation_signals.RegisterValidationInterface(node.peerman.get());1978// ********************************************************* Step 8: start indexers1980if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {1981g_txindex = std::make_unique<TxIndex>(interfaces::MakeChain(node), index_cache_sizes.tx_index, false, do_reindex);1982node.indexes.emplace_back(g_txindex.get());1983}1985if (args.GetBoolArg("-txospenderindex", DEFAULT_TXOSPENDERINDEX)) {1986g_txospenderindex = std::make_unique<TxoSpenderIndex>(interfaces::MakeChain(node), index_cache_sizes.txospender_index, false, do_reindex);1987node.indexes.emplace_back(g_txospenderindex.get());1988}1990for (const auto& filter_type : g_enabled_filter_types) {1991InitBlockFilterIndex([&]{ return interfaces::MakeChain(node); }, filter_type, index_cache_sizes.filter_index, false, do_reindex);1992node.indexes.emplace_back(GetBlockFilterIndex(filter_type));1993}1995if (args.GetBoolArg("-coinstatsindex", DEFAULT_COINSTATSINDEX)) {1996g_coin_stats_index = std::make_unique<CoinStatsIndex>(interfaces::MakeChain(node), /*cache_size=*/0, false, do_reindex);1997node.indexes.emplace_back(g_coin_stats_index.get());1998}2000// Init indexes