Inside Bitcoin
Opening the selected file…
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.
1002// parse and validate enabled filter types1003std::string blockfilterindex_value = args.GetArg("-blockfilterindex", DEFAULT_BLOCKFILTERINDEX);1004if (blockfilterindex_value == "" || blockfilterindex_value == "1") {1005g_enabled_filter_types = AllBlockFilterTypes();1006} else if (blockfilterindex_value != "0") {1007const std::vector<std::string> names = args.GetArgs("-blockfilterindex");1008for (const auto& name : names) {1009BlockFilterType filter_type;1010if (!BlockFilterTypeByName(name, filter_type)) {1011return InitError(strprintf(_("Unknown -blockfilterindex value %s."), name));1012}1013g_enabled_filter_types.insert(filter_type);1014}1015}1017// Signal NODE_P2P_V2 if BIP324 v2 transport is enabled.1018if (args.GetBoolArg("-v2transport", DEFAULT_V2_TRANSPORT)) {1019g_local_services = ServiceFlags(g_local_services | NODE_P2P_V2);1020}1022// Signal NODE_COMPACT_FILTERS if peerblockfilters and basic filters index are both enabled.1023if (args.GetBoolArg("-peerblockfilters", DEFAULT_PEERBLOCKFILTERS)) {1024if (!g_enabled_filter_types.contains(BlockFilterType::BASIC)) {1025return InitError(_("Cannot set -peerblockfilters without -blockfilterindex."));1026}1028g_local_services = ServiceFlags(g_local_services | NODE_COMPACT_FILTERS);1029}1031if (args.GetIntArg("-prune", 0)) {1032if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX))1033return InitError(_("Prune mode is incompatible with -txindex."));1034if (args.GetBoolArg("-txospenderindex", DEFAULT_TXOSPENDERINDEX))1035return InitError(_("Prune mode is incompatible with -txospenderindex."));1036if (args.GetBoolArg("-reindex-chainstate", false)) {1037return InitError(_("Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead."));1038}1039}1041// If -forcednsseed is set to true, ensure -dnsseed has not been set to false1042if (args.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED) && !args.GetBoolArg("-dnsseed", DEFAULT_DNSSEED)){1043return InitError(_("Cannot set -forcednsseed to true when setting -dnsseed to false."));1044}1046// -bind and -whitebind can't be set when not listening1047size_t num_user_p2p_bind = args.GetArgs("-bind").size() + args.GetArgs("-whitebind").size();1048if (num_user_p2p_bind != 0 && !args.GetBoolArg("-listen", DEFAULT_LISTEN)) {1049return InitError(Untranslated("Cannot set -bind or -whitebind together with -listen=0"));1050}1052// if listen=0, then disallow listenonion=11053if (!args.GetBoolArg("-listen", DEFAULT_LISTEN) && args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) {1054return InitError(Untranslated("Cannot set -listen=0 together with -listenonion=1"));1055}1057// Make sure enough file descriptors are available. We need to reserve enough FDs to account for the bare minimum,1058// plus all manual connections and all bound interfaces. Any remainder will be available for connection sockets1060// Number of bound interfaces (we have at least one)1061int num_p2p_bind = std::max(num_user_p2p_bind, size_t(1));1062// Maximum number of connections with other nodes, this accounts for all types of outbounds and inbounds except for manual1063int user_p2p_max_connections = args.GetArg<int>("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS);1064if (user_p2p_max_connections < 0) {1065return InitError(Untranslated("-maxconnections must be greater or equal than zero"));1066}1068if (user_p2p_max_connections > MAX_PEER_CONNECTIONS) {1069InitWarning(strprintf(_("Reducing -maxconnections from %d to %d."), user_p2p_max_connections, MAX_PEER_CONNECTIONS));1070user_p2p_max_connections = MAX_PEER_CONNECTIONS;1071}1073const size_t max_private{args.GetBoolArg("-privatebroadcast", DEFAULT_PRIVATE_BROADCAST)1074? MAX_PRIVATE_BROADCAST_CONNECTIONS1075: 0};1077// HTTP server listen sockets: by default two (IPv4 and IPv6 loopback), or one per -rpcbind entry1078int num_rpc_bind = std::max(args.GetArgs("-rpcbind").size(), size_t(2));1079// HTTP server connected client sockets1080int user_rpc_max_connections = args.GetArg<int>("-rpcmaxconnections", DEFAULT_MAX_HTTP_CONNECTIONS);1081if (user_rpc_max_connections < 1) {1082return InitError(Untranslated("-rpcmaxconnections must be greater than zero. Use -server=0 to disable HTTP."));1083}1084if (!args.GetBoolArg("-server", false)) {1085num_rpc_bind = 0;1086user_rpc_max_connections = 0;1087}1089// Reserve enough FDs to account for the bare minimum, plus any manual connections, plus the bound interfaces.1090// Every element is an int >= 0 so summing in int64_t cannot overflow.1091// RaiseFileDescriptorLimit() accepts an int so we check that limit before casting.1092const int64_t total_fds = int64_t{MIN_CORE_FDS} +1093MAX_ADDNODE_CONNECTIONS +1094num_p2p_bind +1095num_rpc_bind +1096user_rpc_max_connections +1097user_p2p_max_connections +1098static_cast<int64_t>(max_private);1099if (total_fds > std::numeric_limits<int>::max()) {1100return InitError(Untranslated("Too many file descriptors requested. Try lower values for -rpcmaxconnections "1101"or -maxconnections, or fewer settings of "1102"-rpcbind, -bind and -whitebind"));1103}1105// Subset of total_fds must also be a safe int1106int min_required_fds = MIN_CORE_FDS +1107MAX_ADDNODE_CONNECTIONS +1108num_p2p_bind +1109num_rpc_bind +1110user_rpc_max_connections;1112// Try raising the FD limit to what the user wants (available_fds may be smaller than the requested amount if this fails)1113available_fds = RaiseFileDescriptorLimit(static_cast<int>(total_fds));1114// If we are using select instead of poll, our actual limit may be even smaller1115#ifndef USE_POLL1116available_fds = std::min(FD_SETSIZE, available_fds);1117#endif1118// The system can't support our bare minimum1119if (available_fds < min_required_fds)1120return InitError(strprintf(_("Not enough file descriptors available. %d available, %d required."), available_fds, min_required_fds));1122// The system can support our minimum but not the full amount the user requested.1123if (available_fds < total_fds) {1124// If the user is requesting extra HTTP connections, abort. They need to change that.1125if (user_rpc_max_connections > DEFAULT_MAX_HTTP_CONNECTIONS) {1126return InitError(strprintf(_("Not enough file descriptors available. "1127"Try reducing -rpcmaxconnections or using the default value of %d"),1128DEFAULT_MAX_HTTP_CONNECTIONS));1129}1130}1132// Trim requested connection counts, to fit into system limitations1133num_p2p_max_connections = std::min(available_fds - min_required_fds, user_p2p_max_connections);1135if (num_p2p_max_connections < user_p2p_max_connections)1136InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations."), user_p2p_max_connections, num_p2p_max_connections));1138// ********************************************************* Step 3: parameter-to-internal-flags1139if (auto result{init::SetLoggingCategories(args)}; !result) return InitError(util::ErrorString(result));1140if (auto result{init::SetLoggingLevel(args)}; !result) return InitError(util::ErrorString(result));1142nConnectTimeout = args.GetIntArg("-timeout", DEFAULT_CONNECT_TIMEOUT);1143if (nConnectTimeout <= 0) {1144nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;1145}1147peer_connect_timeout = args.GetIntArg("-peertimeout", DEFAULT_PEER_CONNECT_TIMEOUT);1148if (peer_connect_timeout <= 0) {1149return InitError(Untranslated("peertimeout must be a positive integer."));1150}1152auto mining_result{node::ReadMiningArgs(args)};1153if (!mining_result) {1154return InitError(util::ErrorString(mining_result));1155}1157nBytesPerSigOp = args.GetIntArg("-bytespersigop", nBytesPerSigOp);1159if (!g_wallet_init_interface.ParameterInteraction()) return false;1161// Option to startup with mocktime set (used for regression testing):1162if (const auto mocktime{args.GetIntArg("-mocktime")}) {1163SetMockTime(std::chrono::seconds{*mocktime});1164}1166if (args.GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS))1167g_local_services = ServiceFlags(g_local_services | NODE_BLOOM);1169const std::vector<std::string> test_options = args.GetArgs("-test");1170if (!test_options.empty()) {1171if (chainparams.GetChainType() != ChainType::REGTEST) {1172return InitError(Untranslated("-test=<option> can only be used with regtest"));1173}1174for (const std::string& option : test_options) {1175auto it = std::find_if(TEST_OPTIONS_DOC.begin(), TEST_OPTIONS_DOC.end(), [&option](const std::string& doc_option) {1176size_t pos = doc_option.find(" (");1177return (pos != std::string::npos) && (doc_option.substr(0, pos) == option);1178});1179if (it == TEST_OPTIONS_DOC.end()) {1180InitWarning(strprintf(_("Unrecognised option \"%s\" provided in -test=<option>."), option));1181}1182}1183}1185// Prevent setting deployment parameters on mainnet.1186if (chainparams.GetChainType() == ChainType::MAIN) {1187if (args.IsArgSet("-testactivationheight")) {1188return InitError(_("The -testactivationheight option may not be used on mainnet."));1189}1190if (args.IsArgSet("-vbparams")) {1191return InitError(_("The -vbparams option may not be used on mainnet."));1192}1193}1195// Also report errors from parsing before daemonization1196{1197kernel::Notifications notifications{};1198ChainstateManager::Options chainman_opts_dummy{1199.chainparams = chainparams,1200.datadir = args.GetDataDirNet(),1201.notifications = notifications,1202};1203auto chainman_result{ApplyArgsManOptions(args, chainman_opts_dummy)};1204if (!chainman_result) {1205return InitError(util::ErrorString(chainman_result));1206}1207BlockManager::Options blockman_opts_dummy{1208.chainparams = chainman_opts_dummy.chainparams,1209.blocks_dir = args.GetBlocksDirPath(),1210.notifications = chainman_opts_dummy.notifications,1211.block_tree_db_params = DBParams{1212.path = args.GetDataDirNet() / "blocks" / "index",1213.cache_bytes = 0,1214},1215};1216auto blockman_result{ApplyArgsManOptions(args, blockman_opts_dummy)};1217if (!blockman_result) {1218return InitError(util::ErrorString(blockman_result));1219}1220CTxMemPool::Options mempool_opts{};1221auto mempool_result{ApplyArgsManOptions(args, chainparams, mempool_opts)};1222if (!mempool_result) {1223return InitError(util::ErrorString(mempool_result));1224}1225}1227return true;1228}1230static bool LockDirectory(const fs::path& dir, bool probeOnly)1231{1232// Make sure only a single process is using the directory.1233switch (util::LockDirectory(dir, ".lock", probeOnly)) {1234case util::LockResult::ErrorWrite:1235return InitError(strprintf(_("Cannot write to directory '%s'; check permissions."), fs::PathToString(dir)));1236case util::LockResult::ErrorLock:1237return InitError(strprintf(_("Cannot obtain a lock on directory %s. %s is probably already running."), fs::PathToString(dir), CLIENT_NAME));1238case util::LockResult::Success: return true;1239} // no default case, so the compiler can warn about missing cases1240assert(false);1241}1242static bool LockDirectories(bool probeOnly)1243{1244return LockDirectory(gArgs.GetDataDirNet(), probeOnly) && \1245LockDirectory(gArgs.GetBlocksDirPath(), probeOnly);1246}1248bool AppInitSanityChecks(const kernel::Context& kernel)1249{1250// ********************************************************* Step 4: sanity checks