Bitcoin Core
31.1.0
P2P Digital Currency
Toggle main menu visibility
Loading...
Searching...
No Matches
src
bitcoin.cpp
Go to the documentation of this file.
1
// Copyright (c) 2025-present The Bitcoin Core developers
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5
#include <bitcoin-build-config.h>
// IWYU pragma: keep
6
7
#include <
clientversion.h
>
8
#include <
common/args.h
>
9
#include <
common/system.h
>
10
#include <
util/fs.h
>
11
#include <
util/exec.h
>
12
#include <
util/strencodings.h
>
13
#include <
util/translation.h
>
14
15
#include <iostream>
16
#include <string>
17
#include <
tinyformat.h
>
18
#include <vector>
19
20
const
TranslateFn
G_TRANSLATION_FUN
{
nullptr
};
21
22
static
constexpr
auto
HELP_USAGE
= R
"(Usage: %s [OPTIONS] COMMAND...
23
24
Options:
25
-m, --multiprocess Run multiprocess binaries bitcoin-node, bitcoin-gui.
26
-M, --monolithic Run monolithic binaries bitcoind, bitcoin-qt. (Default behavior)
27
-v, --version Show version information
28
-h, --help Show full help message
29
30
Commands:
31
gui [ARGS] Start GUI, equivalent to running 'bitcoin-qt [ARGS]' or 'bitcoin-gui [ARGS]'.
32
node [ARGS] Start node, equivalent to running 'bitcoind [ARGS]' or 'bitcoin-node [ARGS]'.
33
rpc [ARGS] Call RPC method, equivalent to running 'bitcoin-cli -named [ARGS]'.
34
wallet [ARGS] Call wallet command, equivalent to running 'bitcoin-wallet [ARGS]'.
35
tx [ARGS] Manipulate hex-encoded transactions, equivalent to running 'bitcoin-tx [ARGS]'.
36
help Show full help message.
37
)";
38
39
static
constexpr
auto
HELP_FULL
= R
"(
40
Additional less commonly used commands:
41
bench [ARGS] Run bench command, equivalent to running 'bench_bitcoin [ARGS]'.
42
chainstate [ARGS] Run bitcoin kernel chainstate util, equivalent to running 'bitcoin-chainstate [ARGS]'.
43
test [ARGS] Run unit tests, equivalent to running 'test_bitcoin [ARGS]'.
44
test-gui [ARGS] Run GUI unit tests, equivalent to running 'test_bitcoin-qt [ARGS]'.
45
)";
46
47
static
constexpr
auto
HELP_SHORT
= R
"(
48
Run '%s help' to see additional commands (e.g. for testing and debugging).
49
)";
50
51
struct
CommandLine
{
52
std::optional<bool>
use_multiprocess
;
53
bool
show_version
{
false
};
54
bool
show_help
{
false
};
55
std::string_view
command
;
56
std::vector<const char*>
args
;
57
};
58
59
CommandLine
ParseCommandLine
(
int
argc,
char
* argv[]);
60
bool
UseMultiprocess
(
const
CommandLine
&
cmd
);
61
static
void
ExecCommand
(
const
std::vector<const char*>&
args
, std::string_view argv0);
62
63
int
main
(
int
argc,
char
* argv[])
64
{
65
SetupEnvironment
();
66
67
try
{
68
CommandLine
cmd
{
ParseCommandLine
(argc, argv)};
69
if
(
cmd
.show_version) {
70
tfm::format
(std::cout,
"%s version %s\n%s"
, CLIENT_NAME,
FormatFullVersion
(),
FormatParagraph
(
LicenseInfo
()));
71
return
EXIT_SUCCESS
;
72
}
73
74
std::string exe_name{fs::PathToString(fs::PathFromString(argv[0]).filename())};
75
std::vector<const char*>
args
;
76
if
(
cmd
.show_help ||
cmd
.command.empty()) {
77
tfm::format
(std::cout,
HELP_USAGE
, exe_name);
78
if
(
cmd
.show_help) {
79
tfm::format
(std::cout,
HELP_FULL
);
80
return
EXIT_SUCCESS
;
81
}
else
{
82
tfm::format
(std::cout,
HELP_SHORT
, exe_name);
83
return
EXIT_FAILURE;
84
}
85
}
else
if
(
cmd
.command ==
"gui"
) {
86
args
.emplace_back(
UseMultiprocess
(
cmd
) ?
"bitcoin-gui"
:
"bitcoin-qt"
);
87
}
else
if
(
cmd
.command ==
"node"
) {
88
args
.emplace_back(
UseMultiprocess
(
cmd
) ?
"bitcoin-node"
:
"bitcoind"
);
89
}
else
if
(
cmd
.command ==
"rpc"
) {
90
args
.emplace_back(
"bitcoin-cli"
);
91
// Since "bitcoin rpc" is a new interface that doesn't need to be
92
// backward compatible, enable -named by default so it is convenient
93
// for callers to use a mix of named and unnamed parameters. Callers
94
// can override this by specifying -nonamed, but it handles parameters
95
// that contain '=' characters, so -nonamed should rarely be needed.
96
args
.emplace_back(
"-named"
);
97
}
else
if
(
cmd
.command ==
"wallet"
) {
98
args
.emplace_back(
"bitcoin-wallet"
);
99
}
else
if
(
cmd
.command ==
"tx"
) {
100
args
.emplace_back(
"bitcoin-tx"
);
101
}
else
if
(
cmd
.command ==
"bench"
) {
102
args
.emplace_back(
"bench_bitcoin"
);
103
}
else
if
(
cmd
.command ==
"chainstate"
) {
104
args
.emplace_back(
"bitcoin-chainstate"
);
105
}
else
if
(
cmd
.command ==
"test"
) {
106
args
.emplace_back(
"test_bitcoin"
);
107
}
else
if
(
cmd
.command ==
"test-gui"
) {
108
args
.emplace_back(
"test_bitcoin-qt"
);
109
}
else
if
(
cmd
.command ==
"util"
) {
110
args
.emplace_back(
"bitcoin-util"
);
111
}
else
{
112
throw
std::runtime_error(
strprintf
(
"Unrecognized command: '%s'"
,
cmd
.command));
113
}
114
if
(!
args
.empty()) {
115
args
.insert(
args
.end(),
cmd
.args.begin(),
cmd
.args.end());
116
ExecCommand
(
args
, argv[0]);
117
}
118
}
catch
(
const
std::exception& e) {
119
tfm::format
(std::cerr,
"Error: %s\nTry '%s --help' for more information.\n"
, e.what(), argv[0]);
120
return
EXIT_FAILURE;
121
}
122
return
EXIT_SUCCESS
;
123
}
124
125
CommandLine
ParseCommandLine
(
int
argc,
char
* argv[])
126
{
127
CommandLine
cmd
;
128
cmd
.args.reserve(argc);
129
for
(
int
i = 1; i < argc; ++i) {
130
std::string_view arg = argv[i];
131
if
(!
cmd
.command.empty()) {
132
cmd
.args.emplace_back(argv[i]);
133
}
else
if
(arg ==
"-m"
|| arg ==
"--multiprocess"
) {
134
cmd
.use_multiprocess =
true
;
135
}
else
if
(arg ==
"-M"
|| arg ==
"--monolithic"
) {
136
cmd
.use_multiprocess =
false
;
137
}
else
if
(arg ==
"-v"
|| arg ==
"--version"
) {
138
cmd
.show_version =
true
;
139
}
else
if
(arg ==
"-h"
|| arg ==
"--help"
|| arg ==
"help"
) {
140
cmd
.show_help =
true
;
141
}
else
if
(arg.starts_with(
"-"
)) {
142
throw
std::runtime_error(
strprintf
(
"Unknown option: %s"
, arg));
143
}
else
if
(!arg.empty()) {
144
cmd
.command = arg;
145
}
146
}
147
return
cmd
;
148
}
149
150
bool
UseMultiprocess
(
const
CommandLine
&
cmd
)
151
{
152
// If -m or -M options were explicitly specified, there is no need to
153
// further parse arguments to determine which to use.
154
if
(
cmd
.use_multiprocess)
return
*
cmd
.use_multiprocess;
155
156
ArgsManager
args
;
157
args
.SetDefaultFlags(
ArgsManager::ALLOW_ANY
);
158
std::string error_message;
159
auto
argv{
cmd
.args};
160
argv.insert(argv.begin(),
nullptr
);
161
if
(!
args
.ParseParameters(argv.size(), argv.data(), error_message)) {
162
tfm::format
(std::cerr,
"Warning: failed to parse subcommand command line options: %s\n"
, error_message);
163
}
164
if
(!
args
.ReadConfigFiles(error_message,
true
)) {
165
tfm::format
(std::cerr,
"Warning: failed to parse subcommand config: %s\n"
, error_message);
166
}
167
args
.SelectConfigNetwork(
args
.GetChainTypeString());
168
169
// If any -ipc* options are set these need to be processed by a
170
// multiprocess-capable binary.
171
return
args
.IsArgSet(
"-ipcbind"
) ||
args
.IsArgSet(
"-ipcconnect"
) ||
args
.IsArgSet(
"-ipcfd"
);
172
}
173
186
//
192
static
void
ExecCommand
(
const
std::vector<const char*>&
args
, std::string_view wrapper_argv0)
193
{
194
// Construct argument string for execvp
195
std::vector<const char*> exec_args{
args
};
196
exec_args.emplace_back(
nullptr
);
197
198
// Try to call ExecVp with given exe path.
199
auto
try_exec = [&](fs::path exe_path,
bool
allow_notfound =
true
) {
200
std::string exe_path_str{fs::PathToString(exe_path)};
201
exec_args[0] = exe_path_str.c_str();
202
if
(
util::ExecVp
(exec_args[0], (
char
*
const
*)exec_args.data()) == -1) {
203
if
(allow_notfound && errno == ENOENT)
return
false
;
204
throw
std::system_error(errno, std::system_category(),
strprintf
(
"execvp failed to execute '%s'"
, exec_args[0]));
205
}
206
throw
std::runtime_error(
"execvp returned unexpectedly"
);
207
};
208
209
// Get the wrapper executable path.
210
const
fs::path wrapper_path{
util::GetExePath
(wrapper_argv0)};
211
212
// Try to resolve any symlinks and figure out the directory containing the wrapper executable.
213
std::error_code ec;
214
auto
wrapper_dir{fs::weakly_canonical(wrapper_path, ec)};
215
if
(wrapper_dir.empty()) wrapper_dir = wrapper_path;
// Restore previous path if weakly_canonical failed.
216
wrapper_dir = wrapper_dir.parent_path();
217
218
// Get path of the executable to be invoked.
219
const
fs::path arg0{fs::PathFromString(
args
[0])};
220
221
// Decide whether to fall back to the operating system to search for the
222
// specified executable. Avoid doing this if it looks like the wrapper
223
// executable was invoked by path, rather than by search, to avoid
224
// unintentionally launching system executables in a local build.
225
// (https://github.com/bitcoin/bitcoin/pull/31375#discussion_r1861814807)
226
const
bool
fallback_os_search{!fs::PathFromString(std::string{wrapper_argv0}).has_parent_path()};
227
228
// If wrapper is installed in a bin/ directory, look for target executable
229
// in libexec/
230
(wrapper_dir.filename() ==
"bin"
&& try_exec(wrapper_dir.parent_path() /
"libexec"
/ arg0.filename())) ||
231
#ifdef WIN32
232
// Otherwise check the "daemon" subdirectory in a windows install.
233
(!wrapper_dir.empty() && try_exec(wrapper_dir /
"daemon"
/ arg0.filename())) ||
234
#endif
235
// Otherwise look for target executable next to current wrapper
236
(!wrapper_dir.empty() && try_exec(wrapper_dir / arg0.filename(), fallback_os_search)) ||
237
// Otherwise just look on the system path.
238
(fallback_os_search && try_exec(arg0.filename(),
false
));
239
}
args.h
G_TRANSLATION_FUN
const TranslateFn G_TRANSLATION_FUN
Definition
bitcoin-cli.cpp:53
cmd
const auto cmd
Definition
bitcoin-util.cpp:170
SetupEnvironment
SetupEnvironment()
Definition
system.cpp:64
EXIT_SUCCESS
return EXIT_SUCCESS
Definition
bitcoin-wallet.cpp:130
HELP_FULL
static constexpr auto HELP_FULL
Definition
bitcoin.cpp:39
HELP_SHORT
static constexpr auto HELP_SHORT
Definition
bitcoin.cpp:47
ExecCommand
static void ExecCommand(const std::vector< const char * > &args, std::string_view argv0)
Definition
bitcoin.cpp:192
UseMultiprocess
bool UseMultiprocess(const CommandLine &cmd)
Definition
bitcoin.cpp:150
HELP_USAGE
static constexpr auto HELP_USAGE
Definition
bitcoin.cpp:22
ParseCommandLine
CommandLine ParseCommandLine(int argc, char *argv[])
Definition
bitcoin.cpp:125
args
ArgsManager & args
Definition
bitcoind.cpp:277
ArgsManager
Definition
args.h:103
ArgsManager::ALLOW_ANY
@ ALLOW_ANY
disable validation
Definition
args.h:110
FormatFullVersion
std::string FormatFullVersion()
Definition
clientversion.cpp:58
LicenseInfo
std::string LicenseInfo()
Returns licensing information (for -version).
Definition
clientversion.cpp:86
clientversion.h
main
int main(void)
Definition
bench.c:156
exec.h
fs.h
tinyformat::format
void format(std::ostream &out, FormatStringCheck< sizeof...(Args)> fmt, const Args &... args)
Format list of arguments to the stream according to given format string.
Definition
tinyformat.h:1079
util::ExecVp
int ExecVp(const char *file, char *const argv[])
Definition
exec.cpp:21
util::GetExePath
fs::path GetExePath(std::string_view argv0)
Definition
exec.cpp:40
strencodings.h
CommandLine
Definition
bitcoin.cpp:51
CommandLine::command
std::string_view command
Definition
bitcoin.cpp:55
CommandLine::show_version
bool show_version
Definition
bitcoin.cpp:53
CommandLine::args
std::vector< const char * > args
Definition
bitcoin.cpp:56
CommandLine::show_help
bool show_help
Definition
bitcoin.cpp:54
CommandLine::use_multiprocess
std::optional< bool > use_multiprocess
Definition
bitcoin.cpp:52
system.h
tinyformat.h
strprintf
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition
tinyformat.h:1172
translation.h
TranslateFn
std::function< std::string(const char *)> TranslateFn
Translate a message to the native language of the user.
Definition
translation.h:16
FormatParagraph
std::string FormatParagraph(std::string_view in, size_t width, size_t indent)
Format a paragraph of text to a fixed width, adding spaces for indentation to any added line.
Definition
strencodings.cpp:202
Generated on
for Bitcoin Core by
1.17.0