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.
1501auto opt_max_upload = ParseByteUnits(args.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET), ByteUnit::M);1502if (!opt_max_upload) {1503return InitError(strprintf(_("Unable to parse -maxuploadtarget: '%s'"), args.GetArg("-maxuploadtarget", "")));1504}1506// ********************************************************* Step 4a: application initialization1507if (!CreatePidFile(args)) {1508// Detailed error printed inside CreatePidFile().1509return false;1510}1511if (!init::StartLogging(args)) {1512// Detailed error printed inside StartLogging().1513return false;1514}1516LogInfo("Using at most %i automatic connections (%i file descriptors available)", num_p2p_max_connections, available_fds);1518// Warn about relative -datadir path.1519if (args.IsArgSet("-datadir") && !args.GetPathArg("-datadir").is_absolute()) {1520LogWarning("Relative datadir option '%s' specified, which will be interpreted relative to the "1521"current working directory '%s'. This is fragile, because if bitcoin is started in the future "1522"from a different location, it will be unable to locate the current data files. There could "1523"also be data loss if bitcoin is started while in a temporary directory.",1524args.GetArg("-datadir", ""), fs::PathToString(fs::current_path()));1525}1527assert(!node.scheduler);1528node.scheduler = std::make_unique<CScheduler>();1529auto& scheduler = *node.scheduler;1531// Start the lightweight task scheduler thread1532scheduler.m_service_thread = std::thread(util::TraceThread, "scheduler", [&] { scheduler.serviceQueue(); });1534// Gather some entropy once per minute.1535scheduler.scheduleEvery([]{1536RandAddPeriodic();1537}, std::chrono::minutes{1});1539// Check disk space every 5 minutes to avoid db corruption.1540scheduler.scheduleEvery([&args, &node]{1541constexpr uint64_t min_disk_space{50_MiB};1542if (!CheckDiskSpace(args.GetBlocksDirPath(), min_disk_space)) {1543LogError("Shutting down due to lack of disk space!\n");1544if (!(Assert(node.shutdown_request))()) {1545LogError("Failed to send shutdown signal after disk space check\n");1546}1547}1548}, std::chrono::minutes{5});1550if (args.GetBoolArg("-logratelimit", BCLog::DEFAULT_LOGRATELIMIT)) {1551LogInstance().SetRateLimiting(BCLog::LogRateLimiter::Create(1552[&scheduler](auto func, auto window) { scheduler.scheduleEvery(std::move(func), window); },1553BCLog::RATELIMIT_MAX_BYTES,1554BCLog::RATELIMIT_WINDOW));1555} else {1556LogInfo("Log rate limiting disabled");1557}1559assert(!node.validation_signals);1560node.validation_signals = std::make_unique<ValidationSignals>(std::make_unique<SerialTaskRunner>(scheduler));1561auto& validation_signals = *node.validation_signals;1563// Create KernelNotifications object. Important to do this early before1564// calling ipc->listenAddress() below so makeMining and other IPC methods1565// can use this.1566assert(!node.notifications);1567node.notifications = std::make_unique<KernelNotifications>(Assert(node.shutdown_request), node.exit_status, *Assert(node.warnings));1568ReadNotificationArgs(args, *node.notifications);1570// Create client interfaces for wallets that are supposed to be loaded1571// according to -wallet and -disablewallet options. This only constructs1572// the interfaces, it doesn't load wallet data. Wallets actually get loaded1573// when load() and start() interface methods are called below.1574g_wallet_init_interface.Construct(node);1575uiInterface.InitWallet();1577if (interfaces::Ipc* ipc = node.init->ipc()) {1578for (std::string address : gArgs.GetArgs("-ipcbind")) {1579try {1580ipc->listenAddress(address);1581} catch (const std::exception& e) {1582return InitError(Untranslated(strprintf("Unable to bind to IPC address '%s'. %s", address, e.what())));1583}1584LogInfo("Listening for IPC requests on address %s", address);1585}1586}1588/* Register RPC commands regardless of -server setting so they will be1589* available in the GUI RPC console even if external calls are disabled.1590*/1591RegisterAllCoreRPCCommands(tableRPC);1592for (const auto& client : node.chain_clients) {1593client->registerRpcs();1594}1595#ifdef ENABLE_ZMQ1596RegisterZMQRPCCommands(tableRPC);1597#endif1599// Check port numbers1600if (!CheckHostPortOptions(args)) return false;1602// Configure reachable networks before we start the RPC server.1603// This is necessary for -rpcallowip to distinguish CJDNS from other RFC41931604const auto onlynets = args.GetArgs("-onlynet");1605if (!onlynets.empty()) {1606g_reachable_nets.RemoveAll();1607for (const std::string& snet : onlynets) {1608enum Network net = ParseNetwork(snet);1609if (net == NET_UNROUTABLE)1610return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet));1611g_reachable_nets.Add(net);1612}1613}1615if (!args.IsArgSet("-cjdnsreachable")) {1616if (!onlynets.empty() && g_reachable_nets.Contains(NET_CJDNS)) {1617return InitError(1618_("Outbound connections restricted to CJDNS (-onlynet=cjdns) but "1619"-cjdnsreachable is not provided"));1620}1621g_reachable_nets.Remove(NET_CJDNS);1622}1623// Now g_reachable_nets.Contains(NET_CJDNS) is true if:1624// 1. -cjdnsreachable is given and1625// 2.1. -onlynet is not given or1626// 2.2. -onlynet=cjdns is given1628/* Start the RPC server already. It will be started in "warmup" mode1629* and not really process calls already (but it will signify connections1630* that the server is there and will be ready later). Warmup mode will1631* be disabled when initialisation is finished.1632*/1633if (args.GetBoolArg("-server", false)) {1634uiInterface.InitMessage.connect(SetRPCWarmupStatus);1635if (!AppInitServers(node))1636return InitError(_("Unable to start HTTP server. See debug log for details."));1637}1639// ********************************************************* Step 5: verify wallet database integrity1640for (const auto& client : node.chain_clients) {1641if (!client->verify()) {1642return false;1643}1644}1646// ********************************************************* Step 6: network initialization1647// Note that we absolutely cannot open any actual connections1648// until the very end ("start node") as the UTXO/block state1649// is not yet setup and may end up being set up twice if we1650// need to reindex later.1652fListen = args.GetBoolArg("-listen", DEFAULT_LISTEN);1653fDiscover = args.GetBoolArg("-discover", true);1655PeerManager::Options peerman_opts{};1656ApplyArgsManOptions(args, peerman_opts);1658{1659// Read asmap file if configured or embedded asmap data and initialize1660// Netgroupman with or without it1661assert(!node.netgroupman);1662if (args.IsArgSet("-asmap") && !args.IsArgNegated("-asmap")) {1663if (!args.GetBoolArg("-asmap", false)) {1664fs::path asmap_path = args.GetPathArg("-asmap");1665if (!asmap_path.is_absolute()) {1666asmap_path = args.GetDataDirNet() / asmap_path;1667}1669// If a specific path was passed with the asmap argument check if1670// the file actually exists in that location1671if (!fs::exists(asmap_path)) {1672InitError(strprintf(_("Could not find asmap file %s"), fs::quoted(fs::PathToString(asmap_path))));1673return false;1674}1676// If a file exists at the path, try to read the file1677std::vector<std::byte> asmap{DecodeAsmap(asmap_path)};1678if (asmap.empty()) {1679InitError(strprintf(_("Could not parse asmap file %s"), fs::quoted(fs::PathToString(asmap_path))));1680return false;1681}1682node.netgroupman = std::make_unique<NetGroupManager>(NetGroupManager::WithLoadedAsmap(std::move(asmap)));1683} else {1684#ifdef ENABLE_EMBEDDED_ASMAP1685// Use the embedded asmap data1686std::span<const std::byte> asmap{node::data::ip_asn};1687if (asmap.empty() || !CheckStandardAsmap(asmap)) {1688InitError(strprintf(_("Could not read embedded asmap data")));1689return false;1690}1691node.netgroupman = std::make_unique<NetGroupManager>(NetGroupManager::WithEmbeddedAsmap(asmap));1692LogInfo("Opened asmap data (%zu bytes) from embedded byte array\n", asmap.size());1693#else1694// If there is no embedded data, fail and report it since1695// the user tried to use it1696InitError(strprintf(_("Embedded asmap data not available")));1697return false;1698#endif1699}1700LogInfo("Using asmap version %s for IP bucketing", HexStr(node.netgroupman->GetAsmapVersion()));1701} else {1702node.netgroupman = std::make_unique<NetGroupManager>(NetGroupManager::NoAsmap());1703LogInfo("Using /16 prefix for IP bucketing");1704}1706// Initialize addrman1707assert(!node.addrman);1708uiInterface.InitMessage(_("Loading P2P addresses…"));1709auto addrman{LoadAddrman(*node.netgroupman, args)};1710if (!addrman) return InitError(util::ErrorString(addrman));1711node.addrman = std::move(*addrman);1712}1714FastRandomContext rng;1715assert(!node.banman);1716node.banman = std::make_unique<BanMan>(args.GetDataDirNet() / "banlist", &uiInterface, args.GetIntArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));1717assert(!node.connman);1718node.connman = std::make_unique<CConnman>(rng.rand64(),1719rng.rand64(),1720*node.addrman, *node.netgroupman, chainparams, args.GetBoolArg("-networkactive", true));1722for (const std::string& socket_addr : args.GetArgs("-bind")) {1723std::string host_out;1724uint16_t port_out{0};1725std::string bind_socket_addr = socket_addr.substr(0, socket_addr.rfind('='));1726if (!SplitHostPort(bind_socket_addr, port_out, host_out)) {1727return InitError(InvalidPortErrMsg("-bind", socket_addr));1728}1729}1731// sanitize comments per BIP-0014, format user agent and check total size1732std::vector<std::string> uacomments;1733for (const std::string& cmt : args.GetArgs("-uacomment")) {1734if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT))1735return InitError(strprintf(_("User Agent comment (%s) contains unsafe characters."), cmt));1736uacomments.push_back(cmt);1737}1738strSubVersion = FormatSubVersion(UA_NAME, CLIENT_VERSION, uacomments);1739if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) {1740return InitError(strprintf(_("Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments."),1741strSubVersion.size(), MAX_SUBVERSION_LENGTH));1742}1744// Requesting DNS seeds entails connecting to IPv4/IPv6, which -onlynet options may prohibit:1745// If -dnsseed=1 is explicitly specified, abort. If it's left unspecified by the user, we skip1746// the DNS seeds by adjusting -dnsseed in InitParameterInteraction.1747if (args.GetBoolArg("-dnsseed") == true && !g_reachable_nets.Contains(NET_IPV4) && !g_reachable_nets.Contains(NET_IPV6)) {1748return InitError(strprintf(_("Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6")));1749};