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.
1// Copyright (c) 2025-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <bitcoin-build-config.h> // IWYU pragma: keep7#include <clientversion.h>8#include <common/args.h>9#include <common/license_info.h>10#include <common/system.h>11#include <util/fs.h>12#include <util/exec.h>13#include <util/strencodings.h>14#include <util/translation.h>16#include <iostream>17#include <string>18#include <tinyformat.h>19#include <vector>21const TranslateFn G_TRANSLATION_FUN{nullptr};23static constexpr auto HELP_USAGE = R"(Usage: %s [OPTIONS] COMMAND...25Options:26-m, --multiprocess Run multiprocess binaries bitcoin-node, bitcoin-gui.27-M, --monolithic Run monolithic binaries bitcoind, bitcoin-qt. (Default behavior)28-v, --version Show version information29-h, --help Show full help message31Commands:32gui [ARGS] Start GUI, equivalent to running 'bitcoin-qt [ARGS]' or 'bitcoin-gui [ARGS]'.33node [ARGS] Start node, equivalent to running 'bitcoind [ARGS]' or 'bitcoin-node [ARGS]'.34rpc [ARGS] Call RPC method, equivalent to running 'bitcoin-cli -named [ARGS]'.35wallet [ARGS] Call wallet command, equivalent to running 'bitcoin-wallet [ARGS]'.36tx [ARGS] Manipulate hex-encoded transactions, equivalent to running 'bitcoin-tx [ARGS]'.37help Show full help message.38)";40static constexpr auto HELP_FULL = R"(41Additional less commonly used commands:42bench [ARGS] Run bench command, equivalent to running 'bench_bitcoin [ARGS]'.43chainstate [ARGS] Run bitcoin kernel chainstate util, equivalent to running 'bitcoin-chainstate [ARGS]'.44test [ARGS] Run unit tests, equivalent to running 'test_bitcoin [ARGS]'.45test-gui [ARGS] Run GUI unit tests, equivalent to running 'test_bitcoin-qt [ARGS]'.46)";48static constexpr auto HELP_SHORT = R"(49Run '%s help' to see additional commands (e.g. for testing and debugging).50)";52struct CommandLine {53std::optional<bool> use_multiprocess;54bool show_version{false};55bool show_help{false};56std::string_view command;57std::vector<const char*> args;58};60CommandLine ParseCommandLine(int argc, char* argv[]);61bool UseMultiprocess(const CommandLine& cmd);62static void ExecCommand(const std::vector<const char*>& args, std::string_view argv0);64int main(int argc, char* argv[])65{66SetupEnvironment();68try {69CommandLine cmd{ParseCommandLine(argc, argv)};70if (cmd.show_version) {71tfm::format(std::cout, "%s version %s\n%s", CLIENT_NAME, FormatFullVersion(), FormatParagraph(LicenseInfo()));72return EXIT_SUCCESS;73}75std::string exe_name{fs::PathToString(fs::PathFromString(argv[0]).filename())};76std::vector<const char*> args;77if (cmd.show_help || cmd.command.empty()) {78tfm::format(std::cout, HELP_USAGE, exe_name);79if (cmd.show_help) {80tfm::format(std::cout, HELP_FULL);81return EXIT_SUCCESS;82} else {83tfm::format(std::cout, HELP_SHORT, exe_name);84return EXIT_FAILURE;85}86} else if (cmd.command == "gui") {87args.emplace_back(UseMultiprocess(cmd) ? "bitcoin-gui" : "bitcoin-qt");88} else if (cmd.command == "node") {89args.emplace_back(UseMultiprocess(cmd) ? "bitcoin-node" : "bitcoind");90} else if (cmd.command == "rpc") {91args.emplace_back("bitcoin-cli");92// Since "bitcoin rpc" is a new interface that doesn't need to be93// backward compatible, enable -named by default so it is convenient94// for callers to use a mix of named and unnamed parameters. Callers95// can override this by specifying -nonamed, but it handles parameters96// that contain '=' characters, so -nonamed should rarely be needed.97args.emplace_back("-named");98} else if (cmd.command == "wallet") {99args.emplace_back("bitcoin-wallet");100} else if (cmd.command == "tx") {101args.emplace_back("bitcoin-tx");102} else if (cmd.command == "bench") {103args.emplace_back("bench_bitcoin");104} else if (cmd.command == "chainstate") {105args.emplace_back("bitcoin-chainstate");106} else if (cmd.command == "test") {107args.emplace_back("test_bitcoin");108} else if (cmd.command == "test-gui") {109args.emplace_back("test_bitcoin-qt");110} else if (cmd.command == "util") {111args.emplace_back("bitcoin-util");112} else {113throw std::runtime_error(strprintf("Unrecognized command: '%s'", cmd.command));114}115if (!args.empty()) {116args.insert(args.end(), cmd.args.begin(), cmd.args.end());117ExecCommand(args, argv[0]);118}119} catch (const std::exception& e) {120tfm::format(std::cerr, "Error: %s\nTry '%s --help' for more information.\n", e.what(), argv[0]);121return EXIT_FAILURE;122}123return EXIT_SUCCESS;124}126CommandLine ParseCommandLine(int argc, char* argv[])127{128CommandLine cmd;129cmd.args.reserve(argc);130for (int i = 1; i < argc; ++i) {131std::string_view arg = argv[i];132if (!cmd.command.empty()) {133cmd.args.emplace_back(argv[i]);134} else if (arg == "-m" || arg == "--multiprocess") {135cmd.use_multiprocess = true;136} else if (arg == "-M" || arg == "--monolithic") {137cmd.use_multiprocess = false;138} else if (arg == "-v" || arg == "--version") {139cmd.show_version = true;140} else if (arg == "-h" || arg == "--help" || arg == "help") {141cmd.show_help = true;142} else if (arg.starts_with("-")) {143throw std::runtime_error(strprintf("Unknown option: %s", arg));144} else if (!arg.empty()) {145cmd.command = arg;146}147}148return cmd;149}151bool UseMultiprocess(const CommandLine& cmd)152{153// If -m or -M options were explicitly specified, there is no need to154// further parse arguments to determine which to use.155if (cmd.use_multiprocess) return *cmd.use_multiprocess;157ArgsManager args;158args.SetDefaultFlags(ArgsManager::ALLOW_ANY);159std::string error_message;160auto argv{cmd.args};161argv.insert(argv.begin(), nullptr);162if (!args.ParseParameters(argv.size(), argv.data(), error_message)) {163tfm::format(std::cerr, "Warning: failed to parse subcommand command line options: %s\n", error_message);164}165if (!args.ReadConfigFiles(error_message, true)) {166tfm::format(std::cerr, "Warning: failed to parse subcommand config: %s\n", error_message);167}168args.SelectConfigNetwork(args.GetChainTypeString());170// If any -ipc* options are set these need to be processed by a171// multiprocess-capable binary.172return args.IsArgSet("-ipcbind") || args.IsArgSet("-ipcconnect") || args.IsArgSet("-ipcfd");173}175//! Execute the specified bitcoind, bitcoin-qt or other command line in `args`176//! using src, bin and libexec directory paths relative to this executable, where177//! the path to this executable is specified in `wrapper_argv0`.178//!179//! @param args Command line arguments to execute, where first argument should180//! be a relative path to a bitcoind, bitcoin-qt or other executable181//! that will be located on the PATH or relative to wrapper_argv0.182//!183//! @param wrapper_argv0 String containing first command line argument passed to184//! main() to run the current executable. This is used to185//! help determine the path to the current executable and186//! how to look for new executables.187//188//! @note This function doesn't currently print anything but can be debugged189//! from the command line using strace or dtrace like:190//!191//! strace -e trace=execve -s 10000 build/bin/bitcoin ...192//! dtrace -n 'proc:::exec-success /pid == $target/ { trace(curpsinfo->pr_psargs); }' -c ...193static void ExecCommand(const std::vector<const char*>& args, std::string_view wrapper_argv0)194{195// Construct argument string for execvp196std::vector<const char*> exec_args{args};197exec_args.emplace_back(nullptr);199// Try to call ExecVp with given exe path.200auto try_exec = [&](fs::path exe_path, bool allow_notfound = true) {201std::string exe_path_str{fs::PathToString(exe_path)};202exec_args[0] = exe_path_str.c_str();203if (util::ExecVp(exec_args[0], (char*const*)exec_args.data()) == -1) {204if (allow_notfound && errno == ENOENT) return false;205throw std::system_error(errno, std::system_category(), strprintf("execvp failed to execute '%s'", exec_args[0]));206}207throw std::runtime_error("execvp returned unexpectedly");208};210// Get the wrapper executable path.211const fs::path wrapper_path{util::GetExePath(wrapper_argv0)};213// Try to resolve any symlinks and figure out the directory containing the wrapper executable.214std::error_code ec;215auto wrapper_dir{fs::weakly_canonical(wrapper_path, ec)};216if (wrapper_dir.empty()) wrapper_dir = wrapper_path; // Restore previous path if weakly_canonical failed.217wrapper_dir = wrapper_dir.parent_path();219// Get path of the executable to be invoked.220const fs::path arg0{fs::PathFromString(args[0])};222// Decide whether to fall back to the operating system to search for the223// specified executable. Avoid doing this if it looks like the wrapper224// executable was invoked by path, rather than by search, to avoid225// unintentionally launching system executables in a local build.226// (https://github.com/bitcoin/bitcoin/pull/31375#discussion_r1861814807)227const bool fallback_os_search{!fs::PathFromString(std::string{wrapper_argv0}).has_parent_path()};229// If wrapper is installed in a bin/ directory, look for target executable230// in libexec/231(wrapper_dir.filename() == "bin" && try_exec(wrapper_dir.parent_path() / "libexec" / arg0.filename())) ||232#ifdef WIN32233// Otherwise check the "daemon" subdirectory in a windows install.234(!wrapper_dir.empty() && try_exec(wrapper_dir / "daemon" / arg0.filename())) ||235#endif236// Otherwise look for target executable next to current wrapper237(!wrapper_dir.empty() && try_exec(wrapper_dir / arg0.filename(), fallback_os_search)) ||238// Otherwise just look on the system path.239(fallback_os_search && try_exec(arg0.filename(), false));240}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.