Coverage Report

Created: 2026-06-16 16:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/tmp/bitcoin/src/init.cpp
Line
Count
Source
1
// Copyright (c) 2009-2010 Satoshi Nakamoto
2
// Copyright (c) 2009-present The Bitcoin Core developers
3
// Distributed under the MIT software license, see the accompanying
4
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6
#include <bitcoin-build-config.h> // IWYU pragma: keep
7
8
#include <init.h>
9
10
#include <addrdb.h>
11
#include <addrman.h>
12
#include <banman.h>
13
#include <blockfilter.h>
14
#include <chain.h>
15
#include <chainparams.h>
16
#include <chainparamsbase.h>
17
#include <clientversion.h>
18
#include <common/args.h>
19
#include <common/messages.h>
20
#include <common/system.h>
21
#include <compat/compat.h>
22
#include <consensus/params.h>
23
#include <crypto/hex_base.h>
24
#include <dbwrapper.h>
25
#include <httprpc.h>
26
#include <httpserver.h>
27
#include <index/base.h>
28
#include <index/blockfilterindex.h>
29
#include <index/coinstatsindex.h>
30
#include <index/txindex.h>
31
#include <index/txospenderindex.h>
32
#include <init/common.h>
33
#include <interfaces/chain.h>
34
#include <interfaces/init.h>
35
#include <interfaces/ipc.h>
36
#include <interfaces/mining.h>
37
#include <interfaces/node.h>
38
#include <ipc/exception.h>
39
#include <kernel/blockmanager_opts.h>
40
#include <kernel/caches.h>
41
#include <kernel/chainstatemanager_opts.h>
42
#include <kernel/checks.h>
43
#include <kernel/context.h>
44
#include <kernel/notifications_interface.h>
45
#include <key.h>
46
#include <logging.h>
47
#include <mapport.h>
48
#include <net.h>
49
#include <net_permissions.h>
50
#include <net_processing.h>
51
#include <netaddress.h>
52
#include <netbase.h>
53
#include <netgroup.h>
54
#include <node/blockmanager_args.h>
55
#include <node/blockstorage.h>
56
#include <node/caches.h>
57
#include <node/chainstate.h>
58
#include <node/chainstatemanager_args.h>
59
#include <node/context.h>
60
#include <node/interface_ui.h>
61
#include <node/kernel_notifications.h>
62
#include <node/mempool_args.h>
63
#include <node/mempool_persist.h>
64
#include <node/mempool_persist_args.h>
65
#include <node/mining_args.h>
66
#include <node/mining_types.h>
67
#include <node/peerman_args.h>
68
#include <policy/feerate.h>
69
#include <policy/fees/block_policy_estimator.h>
70
#include <policy/fees/block_policy_estimator_args.h>
71
#include <policy/policy.h>
72
#include <policy/settings.h>
73
#include <protocol.h>
74
#include <random.h>
75
#include <rpc/register.h>
76
#include <rpc/server.h>
77
#include <rpc/util.h>
78
#include <scheduler.h>
79
#include <script/sigcache.h>
80
#include <sync.h>
81
#include <tinyformat.h>
82
#include <torcontrol.h>
83
#include <txgraph.h>
84
#include <txmempool.h>
85
#include <uint256.h>
86
#include <util/asmap.h>
87
#include <util/batchpriority.h>
88
#include <util/btcsignals.h>
89
#include <util/chaintype.h>
90
#include <util/check.h>
91
#include <util/fs.h>
92
#include <util/fs_helpers.h>
93
#include <util/moneystr.h>
94
#include <util/result.h>
95
#include <util/signalinterrupt.h>
96
#include <util/strencodings.h>
97
#include <util/string.h>
98
#include <util/syserror.h>
99
#include <util/thread.h>
100
#include <util/threadnames.h>
101
#include <util/time.h>
102
#include <util/translation.h>
103
#include <validation.h>
104
#include <validationinterface.h>
105
#include <walletinitinterface.h>
106
107
#include <algorithm>
108
#include <any>
109
#include <cerrno>
110
#include <condition_variable>
111
#include <cstddef>
112
#include <cstdint>
113
#include <exception>
114
#include <fstream>
115
#include <functional>
116
#include <initializer_list>
117
#include <list>
118
#include <memory>
119
#include <new>
120
#include <optional>
121
#include <set>
122
#include <span>
123
#include <string>
124
#include <system_error>
125
#include <thread>
126
#include <tuple>
127
#include <utility>
128
#include <variant>
129
#include <vector>
130
131
#ifndef WIN32
132
#include <csignal>
133
#endif
134
135
#ifdef ENABLE_ZMQ
136
#include <zmq/zmqabstractnotifier.h>
137
#include <zmq/zmqnotificationinterface.h>
138
#include <zmq/zmqrpc.h>
139
#endif
140
141
#ifdef ENABLE_EMBEDDED_ASMAP
142
#include <node/data/ip_asn.dat.h>
143
#endif
144
145
using common::InvalidPortErrMsg;
146
using common::ResolveErrMsg;
147
148
using node::ApplyArgsManOptions;
149
using node::BlockManager;
150
using node::CalculateCacheSizes;
151
using node::ChainstateLoadResult;
152
using node::ChainstateLoadStatus;
153
using node::DEFAULT_PERSIST_MEMPOOL;
154
using node::DEFAULT_PRINT_MODIFIED_FEE;
155
using node::DEFAULT_STOPATHEIGHT;
156
using node::DumpMempool;
157
using node::ImportBlocks;
158
using node::KernelNotifications;
159
using node::LoadChainstate;
160
using node::LoadMempool;
161
using node::MempoolPath;
162
using node::NodeContext;
163
using node::ShouldPersistMempool;
164
using node::VerifyLoadedChainstate;
165
using util::Join;
166
using util::ReplaceAll;
167
using util::ToString;
168
169
static constexpr bool DEFAULT_PROXYRANDOMIZE{true};
170
static constexpr bool DEFAULT_REST_ENABLE{false};
171
static constexpr bool DEFAULT_I2P_ACCEPT_INCOMING{true};
172
static constexpr bool DEFAULT_STOPAFTERBLOCKIMPORT{false};
173
174
#ifdef WIN32
175
// Win32 LevelDB doesn't use filedescriptors, and the ones used for
176
// accessing block files don't count towards the fd_set size limit
177
// anyway.
178
#define MIN_LEVELDB_FDS 0
179
#else
180
#define MIN_LEVELDB_FDS 150
181
#endif
182
183
static constexpr int MIN_CORE_FDS = MIN_LEVELDB_FDS + NUM_FDS_MESSAGE_CAPTURE;
184
185
/**
186
 * The PID file facilities.
187
 */
188
static const char* BITCOIN_PID_FILENAME = "bitcoind.pid";
189
/**
190
 * True if this process has created a PID file.
191
 * Used to determine whether we should remove the PID file on shutdown.
192
 */
193
static bool g_generated_pid{false};
194
195
static fs::path GetPidFile(const ArgsManager& args)
196
2.27k
{
197
2.27k
    return AbsPathForConfigVal(args, args.GetPathArg("-pid", BITCOIN_PID_FILENAME));
198
2.27k
}
199
200
[[nodiscard]] static bool CreatePidFile(const ArgsManager& args)
201
1.13k
{
202
1.13k
    if (args.IsArgNegated("-pid")) return true;
203
204
1.13k
    std::ofstream file{GetPidFile(args).std_path()};
205
1.13k
    if (file) {
206
#ifdef WIN32
207
        tfm::format(file, "%d\n", GetCurrentProcessId());
208
#else
209
1.13k
        tfm::format(file, "%d\n", getpid());
210
1.13k
#endif
211
1.13k
        g_generated_pid = true;
212
1.13k
        return true;
213
1.13k
    } else {
214
0
        return InitError(strprintf(_("Unable to create the PID file '%s': %s"), fs::PathToString(GetPidFile(args)), SysErrorString(errno)));
215
0
    }
216
1.13k
}
217
218
static void RemovePidFile(const ArgsManager& args)
219
1.15k
{
220
1.15k
    if (!g_generated_pid) return;
221
1.13k
    const auto pid_path{GetPidFile(args)};
222
1.13k
    if (std::error_code error; !fs::remove(pid_path, error)) {
223
0
        std::string msg{error ? error.message() : "File does not exist"};
224
0
        LogWarning("Unable to remove PID file (%s): %s", fs::PathToString(pid_path), msg);
225
0
    }
226
1.13k
}
227
228
static std::optional<util::SignalInterrupt> g_shutdown;
229
230
void InitContext(NodeContext& node)
231
1.20k
{
232
1.20k
    assert(!g_shutdown);
233
1.20k
    g_shutdown.emplace();
234
235
1.20k
    node.args = &gArgs;
236
1.20k
    node.shutdown_signal = &*g_shutdown;
237
1.20k
    node.shutdown_request = [&node] {
238
982
        assert(node.shutdown_signal);
239
982
        if (!(*node.shutdown_signal)()) return false;
240
982
        return true;
241
982
    };
242
1.20k
}
243
244
//////////////////////////////////////////////////////////////////////////////
245
//
246
// Shutdown
247
//
248
249
//
250
// Thread management and startup/shutdown:
251
//
252
// The network-processing threads are all part of a thread group
253
// created by AppInit() or the Qt main() function.
254
//
255
// A clean exit happens when the SignalInterrupt object is triggered, which
256
// makes the main thread's SignalInterrupt::wait() call return, and join all
257
// other ongoing threads in the thread group to the main thread.
258
// Shutdown() is then called to clean up database connections, and stop other
259
// threads that should only be stopped after the main network-processing
260
// threads have exited.
261
//
262
// Shutdown for Qt is very similar, only it uses a QTimer to detect
263
// ShutdownRequested() getting set, and then does the normal Qt
264
// shutdown thing.
265
//
266
267
bool ShutdownRequested(node::NodeContext& node)
268
78.9k
{
269
78.9k
    return bool{*Assert(node.shutdown_signal)};
270
78.9k
}
271
272
#if HAVE_SYSTEM
273
static void ShutdownNotify(const ArgsManager& args)
274
1.15k
{
275
1.15k
    std::vector<std::thread> threads;
276
1.15k
    for (const auto& cmd : args.GetArgs("-shutdownnotify")) {
277
1
        threads.emplace_back(runCommand, cmd);
278
1
    }
279
1.15k
    for (auto& t : threads) {
280
1
        t.join();
281
1
    }
282
1.15k
}
283
#endif
284
285
void Interrupt(NodeContext& node)
286
1.15k
{
287
1.15k
#if HAVE_SYSTEM
288
1.15k
    ShutdownNotify(*node.args);
289
1.15k
#endif
290
    // Wake any threads that may be waiting for the tip to change.
291
1.15k
    if (node.notifications) WITH_LOCK(node.notifications->m_tip_block_mutex, node.notifications->m_tip_block_cv.notify_all());
292
1.15k
    InterruptHTTPServer();
293
1.15k
    InterruptHTTPRPC();
294
1.15k
    InterruptRPC();
295
1.15k
    InterruptREST();
296
1.15k
    if (node.tor_controller) {
297
8
        node.tor_controller->Interrupt();
298
8
    }
299
1.15k
    InterruptMapPort();
300
1.15k
    if (node.connman)
301
1.07k
        node.connman->Interrupt();
302
1.15k
    for (auto* index : node.indexes) {
303
130
        index->Interrupt();
304
130
    }
305
1.15k
}
306
307
void Shutdown(NodeContext& node)
308
1.15k
{
309
1.15k
    static Mutex g_shutdown_mutex;
310
1.15k
    TRY_LOCK(g_shutdown_mutex, lock_shutdown);
311
1.15k
    if (!lock_shutdown) return;
312
1.15k
    LogInfo("Shutdown in progress...");
313
1.15k
    Assert(node.args);
314
315
    /// Note: Shutdown() must be able to handle cases in which initialization failed part of the way,
316
    /// for example if the data directory was found to be locked.
317
    /// Be sure that anything that writes files or flushes caches only does this if the respective
318
    /// module was initialized.
319
1.15k
    util::ThreadRename("shutoff");
320
1.15k
    if (node.mempool) node.mempool->AddTransactionsUpdated(1);
321
322
1.15k
    StopHTTPRPC();
323
1.15k
    StopREST();
324
1.15k
    StopRPC();
325
1.15k
    StopHTTPServer();
326
1.15k
    for (auto& client : node.chain_clients) {
327
398
        try {
328
398
            client->stop();
329
398
        } catch (const ipc::Exception& e) {
330
0
            LogDebug(BCLog::IPC, "Chain client did not disconnect cleanly: %s", e.what());
331
0
            client.reset();
332
0
        }
333
398
    }
334
1.15k
    StopMapPort();
335
336
    // Because these depend on each-other, we make sure that neither can be
337
    // using the other before destroying them.
338
1.15k
    if (node.peerman && node.validation_signals) node.validation_signals->UnregisterValidationInterface(node.peerman.get());
339
1.15k
    if (node.connman) node.connman->Stop();
340
341
1.15k
    if (node.tor_controller) {
342
8
        node.tor_controller->Join();
343
8
        node.tor_controller.reset();
344
8
    }
345
346
1.15k
    if (node.background_init_thread.joinable()) node.background_init_thread.join();
347
    // After everything has been shut down, but before things get flushed, stop the
348
    // the scheduler. After this point, SyncWithValidationInterfaceQueue() should not be called anymore
349
    // as this would prevent the shutdown from completing.
350
1.15k
    if (node.scheduler) node.scheduler->stop();
351
352
    // After the threads that potentially access these pointers have been stopped,
353
    // destruct and reset all to nullptr.
354
1.15k
    node.peerman.reset();
355
1.15k
    node.connman.reset();
356
1.15k
    node.banman.reset();
357
1.15k
    node.addrman.reset();
358
1.15k
    node.netgroupman.reset();
359
360
1.15k
    if (node.mempool && node.mempool->GetLoadTried() && ShouldPersistMempool(*node.args)) {
361
935
        DumpMempool(*node.mempool, MempoolPath(*node.args));
362
935
    }
363
364
    // Drop transactions we were still watching, record fee estimations and unregister
365
    // fee estimator from validation interface.
366
1.15k
    if (node.fee_estimator) {
367
1.06k
        node.fee_estimator->Flush();
368
1.06k
        if (node.validation_signals) {
369
1.06k
            node.validation_signals->UnregisterValidationInterface(node.fee_estimator.get());
370
1.06k
        }
371
1.06k
    }
372
373
    // FlushStateToDisk generates a ChainStateFlushed callback, which we should avoid missing
374
1.15k
    if (node.chainman) {
375
1.04k
        LOCK(cs_main);
376
1.05k
        for (const auto& chainstate : node.chainman->m_chainstates) {
377
1.05k
            if (chainstate->CanFlushToDisk()) {
378
1.04k
                chainstate->ForceFlushStateToDisk();
379
1.04k
            }
380
1.05k
        }
381
1.04k
    }
382
383
    // After there are no more peers/RPC left to give us new data which may generate
384
    // CValidationInterface callbacks, flush them...
385
1.15k
    if (node.validation_signals) node.validation_signals->FlushBackgroundCallbacks();
386
387
    // Stop and delete all indexes only after flushing background callbacks.
388
1.15k
    for (auto* index : node.indexes) index->Stop();
389
1.15k
    if (g_txindex) g_txindex.reset();
390
1.15k
    if (g_txospenderindex) g_txospenderindex.reset();
391
1.15k
    if (g_coin_stats_index) g_coin_stats_index.reset();
392
1.15k
    DestroyAllBlockFilterIndexes();
393
1.15k
    node.indexes.clear(); // all instances are nullptr now
394
395
    // Any future callbacks will be dropped. This should absolutely be safe - if
396
    // missing a callback results in an unrecoverable situation, unclean shutdown
397
    // would too. The only reason to do the above flushes is to let the wallet catch
398
    // up with our current chain to avoid any strange pruning edge cases and make
399
    // next startup faster by avoiding rescan.
400
401
1.15k
    if (node.chainman) {
402
1.04k
        LOCK(cs_main);
403
1.05k
        for (const auto& chainstate : node.chainman->m_chainstates) {
404
1.05k
            if (chainstate->CanFlushToDisk()) {
405
1.04k
                chainstate->ForceFlushStateToDisk();
406
1.04k
                chainstate->ResetCoinsViews();
407
1.04k
            }
408
1.05k
        }
409
1.04k
    }
410
411
    // If any -ipcbind clients are still connected, disconnect them now so they
412
    // do not block shutdown.
413
1.15k
    if (interfaces::Ipc* ipc = node.init->ipc()) {
414
1
        ipc->disconnectIncoming();
415
1
    }
416
417
#ifdef ENABLE_ZMQ
418
    if (g_zmq_notification_interface) {
419
        if (node.validation_signals) node.validation_signals->UnregisterValidationInterface(g_zmq_notification_interface.get());
420
        g_zmq_notification_interface.reset();
421
    }
422
#endif
423
424
1.15k
    node.chain_clients.clear();
425
1.15k
    if (node.validation_signals) {
426
1.13k
        node.validation_signals->UnregisterAllValidationInterfaces();
427
1.13k
    }
428
1.15k
    node.mempool.reset();
429
1.15k
    node.fee_estimator.reset();
430
1.15k
    node.chainman.reset();
431
1.15k
    node.validation_signals.reset();
432
1.15k
    node.scheduler.reset();
433
1.15k
    node.ecc_context.reset();
434
1.15k
    node.kernel.reset();
435
436
1.15k
    RemovePidFile(*node.args);
437
438
1.15k
    LogInfo("Shutdown done");
439
1.15k
}
440
441
/**
442
 * Signal handlers are very limited in what they are allowed to do.
443
 * The execution context the handler is invoked in is not guaranteed,
444
 * so we restrict handler operations to just touching variables:
445
 */
446
#ifndef WIN32
447
static void HandleSIGTERM(int)
448
22
{
449
    // Return value is intentionally ignored because there is not a better way
450
    // of handling this failure in a signal handler.
451
22
    (void)(*Assert(g_shutdown))();
452
22
}
453
454
static void HandleSIGHUP(int)
455
0
{
456
0
    LogInstance().m_reopen_file = true;
457
0
}
458
#else
459
static BOOL WINAPI consoleCtrlHandler(DWORD dwCtrlType)
460
{
461
    if (!(*Assert(g_shutdown))()) {
462
        LogError("Failed to send shutdown signal on Ctrl-C\n");
463
        return false;
464
    }
465
    Sleep(INFINITE);
466
    return true;
467
}
468
#endif
469
470
#ifndef WIN32
471
static void registerSignalHandler(int signal, void(*handler)(int))
472
3.47k
{
473
3.47k
    struct sigaction sa;
474
3.47k
    sa.sa_handler = handler;
475
3.47k
    sigemptyset(&sa.sa_mask);
476
3.47k
    sa.sa_flags = 0;
477
3.47k
    sigaction(signal, &sa, nullptr);
478
3.47k
}
479
#endif
480
481
void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
482
1.88k
{
483
1.88k
    SetupHelpOptions(argsman);
484
1.88k
    argsman.AddArg("-help-debug", "Print help message with debugging options and exit", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST); // server-only for now
485
486
1.88k
    init::AddLoggingArgs(argsman);
487
488
1.88k
    const auto defaultBaseParams = CreateBaseChainParams(ChainType::MAIN);
489
1.88k
    const auto testnetBaseParams = CreateBaseChainParams(ChainType::TESTNET);
490
1.88k
    const auto testnet4BaseParams = CreateBaseChainParams(ChainType::TESTNET4);
491
1.88k
    const auto signetBaseParams = CreateBaseChainParams(ChainType::SIGNET);
492
1.88k
    const auto regtestBaseParams = CreateBaseChainParams(ChainType::REGTEST);
493
1.88k
    const auto defaultChainParams = CreateChainParams(argsman, ChainType::MAIN);
494
1.88k
    const auto testnetChainParams = CreateChainParams(argsman, ChainType::TESTNET);
495
1.88k
    const auto testnet4ChainParams = CreateChainParams(argsman, ChainType::TESTNET4);
496
1.88k
    const auto signetChainParams = CreateChainParams(argsman, ChainType::SIGNET);
497
1.88k
    const auto regtestChainParams = CreateChainParams(argsman, ChainType::REGTEST);
498
499
    // Hidden Options
500
1.88k
    std::vector<std::string> hidden_args = {
501
1.88k
        "-dbcrashratio", "-forcecompactdb",
502
        // GUI args. These will be overwritten by SetupUIArgs for the GUI
503
1.88k
        "-choosedatadir", "-lang=<lang>", "-min", "-resetguisettings", "-splash", "-uiplatform"};
504
505
1.88k
    argsman.AddArg("-version", "Print version and exit", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
506
1.88k
#if HAVE_SYSTEM
507
1.88k
    argsman.AddArg("-alertnotify=<cmd>", "Execute command when an alert is raised (%s in cmd is replaced by message)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
508
1.88k
#endif
509
1.88k
    argsman.AddArg("-assumevalid=<hex>", strprintf("If this block is in the chain assume that it and its ancestors are valid and potentially skip their script verification (0 to verify all, default: %s, testnet3: %s, testnet4: %s, signet: %s)", defaultChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnetChainParams->GetConsensus().defaultAssumeValid.GetHex(), testnet4ChainParams->GetConsensus().defaultAssumeValid.GetHex(), signetChainParams->GetConsensus().defaultAssumeValid.GetHex()), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
510
1.88k
    argsman.AddArg("-blocksdir=<dir>", "Specify directory to hold blocks subdirectory for *.dat files (default: <datadir>)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
511
1.88k
    argsman.AddArg("-blocksxor",
512
1.88k
                   strprintf("Whether an XOR-key applies to blocksdir *.dat files. "
513
1.88k
                             "The created XOR-key will be zeros for an existing blocksdir or when `-blocksxor=0` is "
514
1.88k
                             "set, and random for a freshly initialized blocksdir. "
515
1.88k
                             "(default: %u)",
516
1.88k
                             kernel::DEFAULT_XOR_BLOCKSDIR),
517
1.88k
                   ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
518
1.88k
    argsman.AddArg("-fastprune", "Use smaller block files and lower minimum prune height for testing purposes", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
519
1.88k
#if HAVE_SYSTEM
520
1.88k
    argsman.AddArg("-blocknotify=<cmd>", "Execute command when the best block changes (%s in cmd is replaced by block hash)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
521
1.88k
#endif
522
1.88k
    argsman.AddArg("-blockreconstructionextratxn=<n>", strprintf("Extra transactions to keep in memory for compact block reconstructions (default: %u)", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
523
1.88k
    argsman.AddArg("-blocksonly", strprintf("Whether to reject transactions from network peers. Disables automatic broadcast and rebroadcast of transactions, unless the source peer has the 'forcerelay' permission. RPC transactions are not affected. (default: %u)", DEFAULT_BLOCKSONLY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
524
1.88k
    argsman.AddArg("-coinstatsindex", strprintf("Maintain coinstats index used by the gettxoutsetinfo RPC (default: %u)", DEFAULT_COINSTATSINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
525
1.88k
    argsman.AddArg("-conf=<file>", strprintf("Specify path to read-only configuration file. Relative paths will be prefixed by datadir location (only useable from command line, not configuration file) (default: %s)", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
526
1.88k
    argsman.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_NEGATION, OptionsCategory::OPTIONS);
527
1.88k
    argsman.AddArg("-dbbatchsize", strprintf("Maximum database write batch size in bytes (default: %u)", DEFAULT_DB_CACHE_BATCH), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
528
1.88k
    argsman.AddArg("-dbcache=<n>", strprintf("Maximum database cache size <n> MiB (minimum %d, default: %d). Make sure you have enough RAM. In addition, unused memory allocated to the mempool is shared with this cache (see -maxmempool).", MIN_DB_CACHE >> 20, node::GetDefaultDBCache() >> 20), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
529
1.88k
    argsman.AddArg("-includeconf=<file>", "Specify additional configuration file, relative to the -datadir path (only useable from configuration file, not command line)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
530
1.88k
    argsman.AddArg("-allowignoredconf", strprintf("For backwards compatibility, treat an unused %s file in the datadir as a warning, not an error.", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
531
1.88k
    argsman.AddArg("-loadblock=<file>", "Imports blocks from an external file on startup. Obfuscated blocks are not supported.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
532
1.88k
    argsman.AddArg("-maxmempool=<n>", strprintf("Keep the transaction memory pool below <n> megabytes (default: %u)", DEFAULT_MAX_MEMPOOL_SIZE_MB), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
533
1.88k
    argsman.AddArg("-mempoolexpiry=<n>", strprintf("Do not keep transactions in the mempool longer than <n> hours (default: %u)", DEFAULT_MEMPOOL_EXPIRY_HOURS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
534
1.88k
    argsman.AddArg("-minimumchainwork=<hex>", strprintf("Minimum work assumed to exist on a valid chain in hex (default: %s, testnet3: %s, testnet4: %s, signet: %s)", defaultChainParams->GetConsensus().nMinimumChainWork.GetHex(), testnetChainParams->GetConsensus().nMinimumChainWork.GetHex(), testnet4ChainParams->GetConsensus().nMinimumChainWork.GetHex(), signetChainParams->GetConsensus().nMinimumChainWork.GetHex()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS);
535
1.88k
    argsman.AddArg("-par=<n>", strprintf("Set the number of script verification threads (0 = auto, up to %d, <0 = leave that many cores free, default: %d)",
536
1.88k
        MAX_SCRIPTCHECK_THREADS, DEFAULT_SCRIPTCHECK_THREADS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
537
1.88k
    argsman.AddArg("-persistmempool", strprintf("Whether to save the mempool on shutdown and load on restart (default: %u)", DEFAULT_PERSIST_MEMPOOL), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
538
1.88k
    argsman.AddArg("-persistmempoolv1",
539
1.88k
                   strprintf("Whether a mempool.dat file created by -persistmempool or the savemempool RPC will be written in the legacy format "
540
1.88k
                             "(version 1) or the current format (version 2). This temporary option will be removed in the future. (default: %u)",
541
1.88k
                             DEFAULT_PERSIST_V1_DAT),
542
1.88k
                   ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
543
1.88k
    argsman.AddArg("-pid=<file>", strprintf("Specify pid file. Relative paths will be prefixed by a net-specific datadir location. (default: %s)", BITCOIN_PID_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
544
1.88k
    argsman.AddArg("-prune=<n>", strprintf("Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex. "
545
1.88k
            "Warning: Reverting this setting requires re-downloading the entire blockchain. "
546
1.88k
            "(default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >=%u = automatically prune block files to stay under the specified target size in MiB)", MIN_DISK_SPACE_FOR_BLOCK_FILES / 1_MiB), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
547
1.88k
    argsman.AddArg("-reindex", "If enabled, wipe chain state and block index, and rebuild them from blk*.dat files on disk. Also wipe and rebuild other optional indexes that are active. If an assumeutxo snapshot was loaded, its chainstate will be wiped as well. The snapshot can then be reloaded via RPC.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
548
1.88k
    argsman.AddArg("-reindex-chainstate", "If enabled, wipe chain state, and rebuild it from blk*.dat files on disk. If an assumeutxo snapshot was loaded, its chainstate will be wiped as well. The snapshot can then be reloaded via RPC.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
549
1.88k
    argsman.AddArg("-settings=<file>", strprintf("Specify path to dynamic settings data file. Can be disabled with -nosettings. File is written at runtime and not meant to be edited by users (use %s instead for custom settings). Relative paths will be prefixed by datadir location. (default: %s)", BITCOIN_CONF_FILENAME, BITCOIN_SETTINGS_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
550
1.88k
#if HAVE_SYSTEM
551
1.88k
    argsman.AddArg("-startupnotify=<cmd>", "Execute command on startup.", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
552
1.88k
    argsman.AddArg("-shutdownnotify=<cmd>", "Execute command immediately before beginning shutdown. The need for shutdown may be urgent, so be careful not to delay it long (if the command doesn't require interaction with the server, consider having it fork into the background).", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
553
1.88k
#endif
554
1.88k
    argsman.AddArg("-txindex", strprintf("Maintain a full transaction index, used by the getrawtransaction rpc call (default: %u)", DEFAULT_TXINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
555
1.88k
    argsman.AddArg("-txospenderindex", strprintf("Maintain a transaction output spender index, used by the gettxspendingprevout rpc call (default: %u)", DEFAULT_TXOSPENDERINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
556
1.88k
    argsman.AddArg("-blockfilterindex=<type>",
557
1.88k
                 strprintf("Maintain an index of compact filters by block (default: %s, values: %s).", DEFAULT_BLOCKFILTERINDEX, ListBlockFilterTypes()) +
558
1.88k
                 " If <type> is not supplied or if <type> = 1, indexes for all known types are enabled.",
559
1.88k
                 ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
560
561
1.88k
    argsman.AddArg("-addnode=<ip>", strprintf("Add a node to connect to and attempt to keep the connection open (see the addnode RPC help for more info). This option can be specified multiple times to add multiple nodes; connections are limited to %u at a time and are counted separately from the -maxconnections limit.", MAX_ADDNODE_CONNECTIONS), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
562
1.88k
    argsman.AddArg("-asmap=<file>", strprintf("Specify asn mapping used for bucketing of the peers. Relative paths will be prefixed by the net-specific datadir location.%s",
563
1.88k
                #ifdef ENABLE_EMBEDDED_ASMAP
564
1.88k
                    " If a bool arg is given (-asmap or -asmap=1), the embedded mapping data in the binary will be used."
565
                #else
566
                    ""
567
                #endif
568
1.88k
                ), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
569
1.88k
    argsman.AddArg("-bantime=<n>", strprintf("Default duration (in seconds) of manually configured bans (default: %u)", DEFAULT_MISBEHAVING_BANTIME), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
570
1.88k
    argsman.AddArg("-bind=<addr>[:<port>][=onion]", strprintf("Bind to given address and always listen on it (default: 0.0.0.0). Use [host]:port notation for IPv6. Append =onion to tag any incoming connections to that address and port as incoming Tor connections (default: 127.0.0.1:%u=onion, testnet3: 127.0.0.1:%u=onion, testnet4: 127.0.0.1:%u=onion, signet: 127.0.0.1:%u=onion, regtest: 127.0.0.1:%u=onion)", defaultChainParams->GetDefaultPort() + 1, testnetChainParams->GetDefaultPort() + 1, testnet4ChainParams->GetDefaultPort() + 1, signetChainParams->GetDefaultPort() + 1, regtestChainParams->GetDefaultPort() + 1), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
571
1.88k
    argsman.AddArg("-cjdnsreachable", "If set, then this host is configured for CJDNS (connecting to fc00::/8 addresses would lead us to the CJDNS network, see doc/cjdns.md) (default: 0)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
572
1.88k
    argsman.AddArg("-connect=<ip>", "Connect only to the specified node; -noconnect disables automatic connections (the rules for this peer are the same as for -addnode). This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
573
1.88k
    argsman.AddArg("-discover", "Discover own IP addresses (default: 1 when listening and no -externalip or -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
574
1.88k
    argsman.AddArg("-dns", strprintf("Allow DNS lookups for -addnode, -seednode and -connect (default: %u)", DEFAULT_NAME_LOOKUP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
575
1.88k
    argsman.AddArg("-dnsseed", strprintf("Query for peer addresses via DNS lookup, if low on addresses (default: %u unless -connect used or -maxconnections=0)", DEFAULT_DNSSEED), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
576
1.88k
    argsman.AddArg("-externalip=<ip>", "Specify your own public address", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
577
1.88k
    argsman.AddArg("-fixedseeds", strprintf("Allow fixed seeds if DNS seeds don't provide peers (default: %u)", DEFAULT_FIXEDSEEDS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
578
1.88k
    argsman.AddArg("-forcednsseed", strprintf("Always query for peer addresses via DNS lookup (default: %u)", DEFAULT_FORCEDNSSEED), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
579
1.88k
    argsman.AddArg("-listen", strprintf("Accept connections from outside (default: %u if no -proxy, -connect or -maxconnections=0)", DEFAULT_LISTEN), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
580
1.88k
    argsman.AddArg("-listenonion", strprintf("Automatically create Tor onion service (default: %d)", DEFAULT_LISTEN_ONION), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
581
1.88k
    argsman.AddArg("-maxconnections=<n>", strprintf("Maintain at most <n> automatic connections to peers (default: %u). This limit does not apply to connections manually added via -addnode or the addnode RPC, which have a separate limit of %u. It does not apply to short-lived private broadcast connections either, which have a separate limit of %u.", DEFAULT_MAX_PEER_CONNECTIONS, MAX_ADDNODE_CONNECTIONS, MAX_PRIVATE_BROADCAST_CONNECTIONS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
582
1.88k
    argsman.AddArg("-maxreceivebuffer=<n>", strprintf("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)", DEFAULT_MAXRECEIVEBUFFER), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
583
1.88k
    argsman.AddArg("-maxsendbuffer=<n>", strprintf("Maximum per-connection memory usage for the send buffer, <n>*1000 bytes (default: %u)", DEFAULT_MAXSENDBUFFER), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
584
1.88k
    argsman.AddArg("-maxuploadtarget=<n>", strprintf("Tries to keep outbound traffic under the given target per 24h. Limit does not apply to peers with 'download' permission or blocks created within past week. 0 = no limit (default: %s). Optional suffix units [k|K|m|M|g|G|t|T] (default: M). Lowercase is 1000 base while uppercase is 1024 base", DEFAULT_MAX_UPLOAD_TARGET), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
585
1.88k
#ifdef HAVE_SOCKADDR_UN
586
1.88k
    argsman.AddArg("-onion=<ip:port|path>", "Use separate SOCKS5 proxy to reach peers via Tor onion services, set -noonion to disable (default: -proxy). May be a local file path prefixed with 'unix:'.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
587
#else
588
    argsman.AddArg("-onion=<ip:port>", "Use separate SOCKS5 proxy to reach peers via Tor onion services, set -noonion to disable (default: -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
589
#endif
590
1.88k
    argsman.AddArg("-i2psam=<ip:port>", "I2P SAM proxy to reach I2P peers and accept I2P connections", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
591
1.88k
    argsman.AddArg("-i2pacceptincoming", strprintf("Whether to accept inbound I2P connections (default: %i). Ignored if -i2psam is not set. Listening for inbound I2P connections is done through the SAM proxy, not by binding to a local address and port.", DEFAULT_I2P_ACCEPT_INCOMING), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
592
1.88k
    argsman.AddArg("-onlynet=<net>", "Make automatic outbound connections only to network <net> (" + Join(GetNetworkNames(), ", ") + "). Inbound and manual connections are not affected by this option. It can be specified multiple times to allow multiple networks.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
593
1.88k
    argsman.AddArg("-v2transport", strprintf("Support v2 transport (default: %u)", DEFAULT_V2_TRANSPORT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
594
1.88k
    argsman.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
595
1.88k
    argsman.AddArg("-peerblockfilters", strprintf("Serve compact block filters to peers per BIP 157 (default: %u)", DEFAULT_PEERBLOCKFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
596
1.88k
    argsman.AddArg("-txreconciliation", strprintf("Enable transaction reconciliations per BIP 330 (default: %d)", DEFAULT_TXRECONCILIATION_ENABLE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION);
597
1.88k
    argsman.AddArg("-port=<port>", strprintf("Listen for connections on <port> (default: %u, testnet3: %u, testnet4: %u, signet: %u, regtest: %u). Not relevant for I2P (see doc/i2p.md). If set to a value x, the default onion listening port will be set to x+1.", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), testnet4ChainParams->GetDefaultPort(), signetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
598
1.88k
    const std::string proxy_doc_for_value =
599
1.88k
#ifdef HAVE_SOCKADDR_UN
600
1.88k
        "<ip>[:<port>]|unix:<path>";
601
#else
602
        "<ip>[:<port>]";
603
#endif
604
1.88k
    const std::string proxy_doc_for_unix_socket =
605
1.88k
#ifdef HAVE_SOCKADDR_UN
606
1.88k
        "May be a local file path prefixed with 'unix:' if the proxy supports it. ";
607
#else
608
        "";
609
#endif
610
1.88k
    argsman.AddArg("-proxy=" + proxy_doc_for_value + "[=<network>]",
611
1.88k
                   "Connect through SOCKS5 proxy, set -noproxy to disable. " +
612
1.88k
                   proxy_doc_for_unix_socket +
613
1.88k
                   "Could end in =network to set the proxy only for that network. " +
614
1.88k
                   "The network can be any of ipv4, ipv6, tor or cjdns. " +
615
1.88k
                   "(default: disabled)",
616
1.88k
                   ArgsManager::ALLOW_ANY | ArgsManager::DISALLOW_ELISION,
617
1.88k
                   OptionsCategory::CONNECTION);
618
1.88k
    argsman.AddArg("-proxyrandomize", strprintf("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)", DEFAULT_PROXYRANDOMIZE), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
619
1.88k
    argsman.AddArg("-seednode=<ip>", "Connect to a node to retrieve peer addresses, and disconnect. This option can be specified multiple times to connect to multiple nodes. During startup, seednodes will be tried before dnsseeds.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
620
1.88k
    argsman.AddArg("-networkactive", "Enable all P2P network activity (default: 1). Can be changed by the setnetworkactive RPC command", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
621
1.88k
    argsman.AddArg("-timeout=<n>", strprintf("Specify socket connection timeout in milliseconds. If an initial attempt to connect is unsuccessful after this amount of time, drop it (minimum: 1, default: %d)", DEFAULT_CONNECT_TIMEOUT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
622
1.88k
    argsman.AddArg("-peertimeout=<n>", strprintf("Specify a p2p connection timeout delay in seconds. After connecting to a peer, wait this amount of time before considering disconnection based on inactivity (minimum: 1, default: %d)", DEFAULT_PEER_CONNECT_TIMEOUT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION);
623
1.88k
    argsman.AddArg("-torcontrol=<ip>:<port>", strprintf("Tor control host and port to use if onion listening enabled (default: %s). If no port is specified, the default port of %i will be used.", DEFAULT_TOR_CONTROL, DEFAULT_TOR_CONTROL_PORT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
624
1.88k
    argsman.AddArg("-torpassword=<pass>", "Tor control port password (default: empty)", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::CONNECTION);
625
1.88k
    argsman.AddArg("-natpmp", strprintf("Use PCP or NAT-PMP to map the listening port (default: %u)", DEFAULT_NATPMP), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
626
1.88k
    argsman.AddArg("-whitebind=<[permissions@]addr>", "Bind to the given address and add permission flags to the peers connecting to it. "
627
1.88k
        "Use [host]:port notation for IPv6. Allowed permissions: " + Join(NET_PERMISSIONS_DOC, ", ") + ". "
628
1.88k
        "Specify multiple permissions separated by commas (default: download,noban,mempool,relay). Can be specified multiple times.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
629
630
1.88k
    argsman.AddArg("-whitelist=<[permissions@]IP address or network>", "Add permission flags to the peers using the given IP address (e.g. 1.2.3.4) or "
631
1.88k
        "CIDR-notated network (e.g. 1.2.3.0/24). Uses the same permissions as "
632
1.88k
        "-whitebind. "
633
1.88k
        "Additional flags \"in\" and \"out\" control whether permissions apply to incoming connections and/or manual (default: incoming only). "
634
1.88k
        "Can be specified multiple times.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
635
636
1.88k
    g_wallet_init_interface.AddWalletOptions(argsman);
637
638
#ifdef ENABLE_ZMQ
639
    argsman.AddArg("-zmqpubhashblock=<address>", "Enable publish hash block in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
640
    argsman.AddArg("-zmqpubhashtx=<address>", "Enable publish hash transaction in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
641
    argsman.AddArg("-zmqpubrawblock=<address>", "Enable publish raw block in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
642
    argsman.AddArg("-zmqpubrawtx=<address>", "Enable publish raw transaction in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
643
    argsman.AddArg("-zmqpubsequence=<address>", "Enable publish hash block and tx sequence in <address>", ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
644
    argsman.AddArg("-zmqpubhashblockhwm=<n>", strprintf("Set publish hash block outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
645
    argsman.AddArg("-zmqpubhashtxhwm=<n>", strprintf("Set publish hash transaction outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
646
    argsman.AddArg("-zmqpubrawblockhwm=<n>", strprintf("Set publish raw block outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
647
    argsman.AddArg("-zmqpubrawtxhwm=<n>", strprintf("Set publish raw transaction outbound message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
648
    argsman.AddArg("-zmqpubsequencehwm=<n>", strprintf("Set publish hash sequence message high water mark (default: %d)", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM), ArgsManager::ALLOW_ANY, OptionsCategory::ZMQ);
649
#else
650
1.88k
    hidden_args.emplace_back("-zmqpubhashblock=<address>");
651
1.88k
    hidden_args.emplace_back("-zmqpubhashtx=<address>");
652
1.88k
    hidden_args.emplace_back("-zmqpubrawblock=<address>");
653
1.88k
    hidden_args.emplace_back("-zmqpubrawtx=<address>");
654
1.88k
    hidden_args.emplace_back("-zmqpubsequence=<n>");
655
1.88k
    hidden_args.emplace_back("-zmqpubhashblockhwm=<n>");
656
1.88k
    hidden_args.emplace_back("-zmqpubhashtxhwm=<n>");
657
1.88k
    hidden_args.emplace_back("-zmqpubrawblockhwm=<n>");
658
1.88k
    hidden_args.emplace_back("-zmqpubrawtxhwm=<n>");
659
1.88k
    hidden_args.emplace_back("-zmqpubsequencehwm=<n>");
660
1.88k
#endif
661
662
1.88k
    argsman.AddArg("-checkblocks=<n>", strprintf("How many blocks to check at startup (default: %u, 0 = all)", DEFAULT_CHECKBLOCKS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
663
1.88k
    argsman.AddArg("-checklevel=<n>", strprintf("How thorough the block verification of -checkblocks is: %s (0-4, default: %u)", Join(CHECKLEVEL_DOC, ", "), DEFAULT_CHECKLEVEL), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
664
1.88k
    argsman.AddArg("-checkblockindex", strprintf("Do a consistency check for the block tree, chainstate, and other validation data structures every <n> operations. Use 0 to disable. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
665
1.88k
    argsman.AddArg("-checkaddrman=<n>", strprintf("Run addrman consistency checks every <n> operations. Use 0 to disable. (default: %u)", DEFAULT_ADDRMAN_CONSISTENCY_CHECKS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
666
1.88k
    argsman.AddArg("-checkmempool=<n>", strprintf("Run mempool consistency checks every <n> transactions. Use 0 to disable. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
667
    // Checkpoints were removed. We keep `-checkpoints` as a hidden arg to display a more user friendly error when set.
668
1.88k
    argsman.AddArg("-checkpoints", "", ArgsManager::ALLOW_ANY, OptionsCategory::HIDDEN);
669
1.88k
    argsman.AddArg("-deprecatedrpc=<method>", "Allows deprecated RPC method(s) to be used", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
670
1.88k
    argsman.AddArg("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
671
1.88k
    argsman.AddArg("-stopatheight", strprintf("Stop running after reaching the given height in the main chain (default: %u). Blocks after target height may be processed during shutdown.", DEFAULT_STOPATHEIGHT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
672
1.88k
    argsman.AddArg("-limitancestorcount=<n>", strprintf("Deprecated setting to not accept transactions if number of in-mempool ancestors is <n> or more (default: %u); replaced by cluster limits (see -limitclustercount) and only used by wallet for coin selection", DEFAULT_ANCESTOR_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
673
    // Ancestor and descendant size limits were removed. We keep
674
    // -limitancestorsize/-limitdescendantsize as hidden args to display a more
675
    // user friendly error when set.
676
1.88k
    argsman.AddArg("-limitancestorsize", "", ArgsManager::ALLOW_ANY, OptionsCategory::HIDDEN);
677
1.88k
    argsman.AddArg("-limitdescendantsize", "", ArgsManager::ALLOW_ANY, OptionsCategory::HIDDEN);
678
1.88k
    argsman.AddArg("-limitdescendantcount=<n>", strprintf("Deprecated setting to not accept transactions if any ancestor would have <n> or more in-mempool descendants (default: %u); replaced by cluster limits (see -limitclustercount) and only used by wallet for coin selection", DEFAULT_DESCENDANT_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
679
1.88k
    argsman.AddArg("-test=<option>", "Pass a test-only option. Options include : " + Join(TEST_OPTIONS_DOC, ", ") + ".", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
680
1.88k
    argsman.AddArg("-limitclustercount=<n>", strprintf("Do not accept transactions into mempool which are directly or indirectly connected to <n> or more other unconfirmed transactions (default: %u, maximum: %u)", DEFAULT_CLUSTER_LIMIT, MAX_CLUSTER_COUNT_LIMIT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
681
1.88k
    argsman.AddArg("-limitclustersize=<n>", strprintf("Do not accept transactions whose virtual size with all in-mempool connected transactions exceeds <n> kilobytes (default: %u)", DEFAULT_CLUSTER_SIZE_LIMIT_KVB), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
682
1.88k
    argsman.AddArg("-capturemessages", "Capture all P2P messages to disk", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
683
1.88k
    argsman.AddArg("-mocktime=<n>", "Replace actual time with " + UNIX_EPOCH_TIME + " (default: 0)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
684
1.88k
    argsman.AddArg("-maxsigcachesize=<n>", strprintf("Limit sum of signature cache and script execution cache sizes to <n> MiB (default: %u)", DEFAULT_VALIDATION_CACHE_BYTES >> 20), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
685
1.88k
    argsman.AddArg("-maxtipage=<n>",
686
1.88k
                   strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)",
687
1.88k
                             Ticks<std::chrono::seconds>(DEFAULT_MAX_TIP_AGE)),
688
1.88k
                   ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
689
1.88k
    argsman.AddArg("-printpriority", strprintf("Log transaction fee rate in %s/kvB when mining blocks (default: %u)", CURRENCY_UNIT, DEFAULT_PRINT_MODIFIED_FEE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
690
1.88k
    argsman.AddArg("-uacomment=<cmt>", "Append comment to the user agent string", ArgsManager::ALLOW_ANY, OptionsCategory::DEBUG_TEST);
691
692
1.88k
    SetupChainParamsBaseOptions(argsman);
693
694
1.88k
    argsman.AddArg("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (test networks only; default: %u)", DEFAULT_ACCEPT_NON_STD_TXN), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
695
1.88k
    argsman.AddArg("-incrementalrelayfee=<amt>", strprintf("Fee rate (in %s/kvB) used to define cost of relay, used for mempool limiting and replacement policy. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
696
1.88k
    argsman.AddArg("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kvB) used to define dust, the value of an output such that it will cost more than its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::NODE_RELAY);
697
1.88k
    argsman.AddArg("-acceptstalefeeestimates", strprintf("Read fee estimates even if they are stale (%sdefault: %u) fee estimates are considered stale if they are %s hours old", "regtest only; ", DEFAULT_ACCEPT_STALE_FEE_ESTIMATES, Ticks<std::chrono::hours>(MAX_FILE_AGE)), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
698
1.88k
    argsman.AddArg("-bytespersigop", strprintf("Equivalent bytes per sigop in transactions for relay and mining (default: %u)", DEFAULT_BYTES_PER_SIGOP), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
699
1.88k
    argsman.AddArg("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
700
1.88k
    argsman.AddArg("-datacarriersize",
701
1.88k
                   strprintf("Relay and mine transactions whose data-carrying raw scriptPubKeys in aggregate "
702
1.88k
                             "are of this size or less, allowing multiple outputs (default: %u)",
703
1.88k
                             MAX_OP_RETURN_RELAY),
704
1.88k
                   ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
705
1.88k
    argsman.AddArg("-permitbaremultisig", strprintf("Relay transactions creating non-P2SH multisig outputs (default: %u)", DEFAULT_PERMIT_BAREMULTISIG), ArgsManager::ALLOW_ANY,
706
1.88k
                   OptionsCategory::NODE_RELAY);
707
1.88k
    argsman.AddArg("-minrelaytxfee=<amt>", strprintf("Fees (in %s/kvB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)",
708
1.88k
        CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
709
1.88k
    argsman.AddArg("-privatebroadcast",
710
1.88k
                   strprintf(
711
1.88k
                       "Broadcast transactions submitted via sendrawtransaction RPC using short-lived "
712
1.88k
                       "connections through the Tor or I2P networks, without putting them in the mempool first. "
713
1.88k
                       "Transactions submitted through the wallet are not affected by this option "
714
1.88k
                       "(default: %u)",
715
1.88k
                   DEFAULT_PRIVATE_BROADCAST),
716
1.88k
                   ArgsManager::ALLOW_ANY,
717
1.88k
                   OptionsCategory::NODE_RELAY);
718
1.88k
    argsman.AddArg("-whitelistforcerelay", strprintf("Add 'forcerelay' permission to whitelisted peers with default permissions. This will relay transactions even if the transactions were already in the mempool. (default: %d)", DEFAULT_WHITELISTFORCERELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
719
1.88k
    argsman.AddArg("-whitelistrelay", strprintf("Add 'relay' permission to whitelisted peers with default permissions. This will accept relayed transactions even when not relaying transactions (default: %d)", DEFAULT_WHITELISTRELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
720
721
722
1.88k
    argsman.AddArg("-blockmaxweight=<n>", strprintf("Set maximum BIP141 block weight (default: %d)", DEFAULT_BLOCK_MAX_WEIGHT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::BLOCK_CREATION);
723
1.88k
    argsman.AddArg("-blockreservedweight=<n>", strprintf("Reserve space for the fixed-size block header plus the largest coinbase transaction the mining software may add to the block. Only affects mining RPC clients, not IPC clients. (default: %d).", DEFAULT_BLOCK_RESERVED_WEIGHT), ArgsManager::ALLOW_ANY, OptionsCategory::BLOCK_CREATION);
724
1.88k
    argsman.AddArg("-blockmintxfee=<amt>", strprintf("Set lowest fee rate (in %s/kvB) for transactions to be included in block creation. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_BLOCK_MIN_TX_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::BLOCK_CREATION);
725
1.88k
    argsman.AddArg("-blockversion=<n>", "Override block version to test forking scenarios", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::BLOCK_CREATION);
726
727
1.88k
    argsman.AddArg("-rest", strprintf("Accept public REST requests (default: %u)", DEFAULT_REST_ENABLE), ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
728
1.88k
    argsman.AddArg("-rpcallowip=<ip>", "Allow JSON-RPC connections from specified source. Valid values for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0), a network/CIDR (e.g. 1.2.3.4/24), all ipv4 (0.0.0.0/0), or all ipv6 (::/0). RFC4193 is allowed only if -cjdnsreachable=0. This option can be specified multiple times", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
729
1.88k
    argsman.AddArg("-rpcauth=<userpw>", "Username and HMAC-SHA-256 hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcauth. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
730
1.88k
    argsman.AddArg("-rpcbind=<addr>[:port]", "Bind to given address to listen for JSON-RPC connections. Do not expose the RPC server to untrusted networks such as the public internet! This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times (default: 127.0.0.1 and ::1 i.e., localhost)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::RPC);
731
1.88k
    argsman.AddArg("-rpcdoccheck", strprintf("Throw a non-fatal error at runtime if the documentation for an RPC is incorrect (default: %u)", DEFAULT_RPC_DOC_CHECK), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::RPC);
732
1.88k
    argsman.AddArg("-rpccookiefile=<loc>", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
733
1.88k
    argsman.AddArg("-rpccookieperms=<readable-by>", strprintf("Set permissions on the RPC auth cookie file so that it is readable by [owner|group|all] (default: owner [via umask 0077])"), ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
734
1.88k
    argsman.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
735
1.88k
    argsman.AddArg("-rpcport=<port>", strprintf("Listen for JSON-RPC connections on <port> (default: %u, testnet3: %u, testnet4: %u, signet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), testnet4BaseParams->RPCPort(), signetBaseParams->RPCPort(), regtestBaseParams->RPCPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::RPC);
736
1.88k
    argsman.AddArg("-rpcservertimeout=<n>", strprintf("Timeout during HTTP requests (default: %d)", DEFAULT_HTTP_SERVER_TIMEOUT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::RPC);
737
1.88k
    argsman.AddArg("-rpcthreads=<n>", strprintf("Set the number of threads to service RPC calls (default: %d)", DEFAULT_HTTP_THREADS), ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
738
1.88k
    argsman.AddArg("-rpcuser=<user>", "Username for JSON-RPC connections", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
739
1.88k
    argsman.AddArg("-rpcwhitelist=<whitelist>", "Set a whitelist to filter incoming RPC calls for a specific user. The field <whitelist> comes in the format: <USERNAME>:<rpc 1>,<rpc 2>,...,<rpc n>. If multiple whitelists are set for a given user, they are set-intersected. See -rpcwhitelistdefault documentation for information on default whitelist behavior.", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
740
1.88k
    argsman.AddArg("-rpcwhitelistdefault", "Sets default behavior for rpc whitelisting. Unless rpcwhitelistdefault is set to 0, if any -rpcwhitelist is set, the rpc server acts as if all rpc users are subject to empty-unless-otherwise-specified whitelists. If rpcwhitelistdefault is set to 1 and no -rpcwhitelist is set, rpc server acts as if all rpc users are subject to empty whitelists.", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
741
1.88k
    argsman.AddArg("-rpcworkqueue=<n>", strprintf("Set the maximum depth of the work queue to service RPC calls (default: %d)", DEFAULT_HTTP_WORKQUEUE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::RPC);
742
1.88k
    argsman.AddArg("-server", "Accept command line and JSON-RPC commands", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
743
1.88k
    if (can_listen_ipc) {
744
5
        argsman.AddArg("-ipcbind=<address>", "Bind to Unix socket address and listen for incoming connections. Valid address values are \"unix\" to listen on the default path, <datadir>/node.sock, or \"unix:/custom/path\" to specify a custom path. Can be specified multiple times to listen on multiple paths. Default behavior is not to listen on any path. If relative paths are specified, they are interpreted relative to the network data directory. If paths include any parent directory components and the parent directories do not exist, they will be created. Enabling this gives local processes that can access the socket unauthenticated RPC access, so it's important to choose a path with secure permissions if customizing this.", ArgsManager::ALLOW_ANY, OptionsCategory::IPC);
745
5
    }
746
747
1.88k
#if HAVE_DECL_FORK
748
1.88k
    argsman.AddArg("-daemon", strprintf("Run in the background as a daemon and accept commands (default: %d)", DEFAULT_DAEMON), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
749
1.88k
    argsman.AddArg("-daemonwait", strprintf("Wait for initialization to be finished before exiting. This implies -daemon (default: %d)", DEFAULT_DAEMONWAIT), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
750
#else
751
    hidden_args.emplace_back("-daemon");
752
    hidden_args.emplace_back("-daemonwait");
753
#endif
754
755
    // Add the hidden options
756
1.88k
    argsman.AddHiddenArgs(hidden_args);
757
1.88k
}
758
759
#if HAVE_SYSTEM
760
static void StartupNotify(const ArgsManager& args)
761
994
{
762
994
    std::string cmd = args.GetArg("-startupnotify", "");
763
994
    if (!cmd.empty()) {
764
1
        std::thread t(runCommand, cmd);
765
1
        t.detach(); // thread runs free
766
1
    }
767
994
}
768
#endif
769
770
static bool AppInitServers(NodeContext& node)
771
1.11k
{
772
1.11k
    const ArgsManager& args = *Assert(node.args);
773
1.11k
    if (!InitHTTPServer(*Assert(node.shutdown_signal))) {
774
1
        return false;
775
1
    }
776
1.11k
    StartRPC();
777
1.11k
    node.rpc_interruption_point = RpcInterruptionPoint;
778
1.11k
    if (!StartHTTPRPC(&node))
779
12
        return false;
780
1.10k
    if (args.GetBoolArg("-rest", DEFAULT_REST_ENABLE)) StartREST(&node);
781
1.10k
    StartHTTPServer();
782
1.10k
    return true;
783
1.11k
}
784
785
// Parameter interaction based on rules
786
void InitParameterInteraction(ArgsManager& args)
787
1.15k
{
788
    // when specifying an explicit binding address, you want to listen on it
789
    // even when -connect or -proxy is specified
790
1.15k
    if (!args.GetArgs("-bind").empty()) {
791
1.11k
        if (args.SoftSetBoolArg("-listen", true))
792
1.11k
            LogInfo("parameter interaction: -bind set -> setting -listen=1\n");
793
1.11k
    }
794
1.15k
    if (!args.GetArgs("-whitebind").empty()) {
795
9
        if (args.SoftSetBoolArg("-listen", true))
796
9
            LogInfo("parameter interaction: -whitebind set -> setting -listen=1\n");
797
9
    }
798
799
1.15k
    if (!args.GetArgs("-connect").empty() || args.IsArgNegated("-connect") || args.GetIntArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS) <= 0) {
800
        // when only connecting to trusted nodes, do not seed via DNS, or listen by default
801
        // do the same when connections are disabled
802
1.12k
        if (args.SoftSetBoolArg("-dnsseed", false))
803
1.12k
            LogInfo("parameter interaction: -connect or -maxconnections=0 set -> setting -dnsseed=0\n");
804
1.12k
        if (args.SoftSetBoolArg("-listen", false))
805
1.12k
            LogInfo("parameter interaction: -connect or -maxconnections=0 set -> setting -listen=0\n");
806
1.12k
    }
807
808
1.15k
    std::string proxy_arg = args.GetArg("-proxy", "");
809
1.15k
    if (proxy_arg != "" && proxy_arg != "0") {
810
        // to protect privacy, do not listen by default if a default proxy server is specified
811
47
        if (args.SoftSetBoolArg("-listen", false))
812
47
            LogInfo("parameter interaction: -proxy set -> setting -listen=0\n");
813
        // to protect privacy, do not map ports when a proxy is set. The user may still specify -listen=1
814
        // to listen locally, so don't rely on this happening through -listen below.
815
47
        if (args.SoftSetBoolArg("-natpmp", false)) {
816
0
            LogInfo("parameter interaction: -proxy set -> setting -natpmp=0\n");
817
0
        }
818
        // to protect privacy, do not discover addresses by default
819
47
        if (args.SoftSetBoolArg("-discover", false))
820
47
            LogInfo("parameter interaction: -proxy set -> setting -discover=0\n");
821
47
    }
822
823
1.15k
    if (!args.GetBoolArg("-listen", DEFAULT_LISTEN)) {
824
        // do not map ports or try to retrieve public IP when not listening (pointless)
825
33
        if (args.SoftSetBoolArg("-natpmp", false)) {
826
0
            LogInfo("parameter interaction: -listen=0 -> setting -natpmp=0\n");
827
0
        }
828
33
        if (args.SoftSetBoolArg("-discover", false))
829
33
            LogInfo("parameter interaction: -listen=0 -> setting -discover=0\n");
830
33
        if (args.SoftSetBoolArg("-listenonion", false))
831
33
            LogInfo("parameter interaction: -listen=0 -> setting -listenonion=0\n");
832
33
        if (args.SoftSetBoolArg("-i2pacceptincoming", false)) {
833
33
            LogInfo("parameter interaction: -listen=0 -> setting -i2pacceptincoming=0\n");
834
33
        }
835
33
    }
836
837
1.15k
    if (!args.GetArgs("-externalip").empty()) {
838
        // if an explicit public IP is specified, do not try to find others
839
12
        if (args.SoftSetBoolArg("-discover", false))
840
12
            LogInfo("parameter interaction: -externalip set -> setting -discover=0\n");
841
12
    }
842
843
1.15k
    if (args.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)) {
844
        // disable whitelistrelay in blocksonly mode
845
7
        if (args.SoftSetBoolArg("-whitelistrelay", false))
846
7
            LogInfo("parameter interaction: -blocksonly=1 -> setting -whitelistrelay=0\n");
847
        // Reduce default mempool size in blocksonly mode to avoid unexpected resource usage
848
7
        if (args.SoftSetArg("-maxmempool", ToString(DEFAULT_BLOCKSONLY_MAX_MEMPOOL_SIZE_MB)))
849
7
            LogInfo("parameter interaction: -blocksonly=1 -> setting -maxmempool=%d\n", DEFAULT_BLOCKSONLY_MAX_MEMPOOL_SIZE_MB);
850
7
    }
851
852
    // Forcing relay from whitelisted hosts implies we will accept relays from them in the first place.
853
1.15k
    if (args.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) {
854
3
        if (args.SoftSetBoolArg("-whitelistrelay", true))
855
3
            LogInfo("parameter interaction: -whitelistforcerelay=1 -> setting -whitelistrelay=1\n");
856
3
    }
857
1.15k
    const auto onlynets = args.GetArgs("-onlynet");
858
1.15k
    if (!onlynets.empty()) {
859
8
        bool clearnet_reachable = std::any_of(onlynets.begin(), onlynets.end(), [](const auto& net) {
860
8
            const auto n = ParseNetwork(net);
861
8
            return n == NET_IPV4 || n == NET_IPV6;
862
8
        });
863
8
        if (!clearnet_reachable && args.SoftSetBoolArg("-dnsseed", false)) {
864
0
            LogInfo("parameter interaction: -onlynet excludes IPv4 and IPv6 -> setting -dnsseed=0\n");
865
0
        }
866
8
    }
867
1.15k
}
868
869
/**
870
 * Initialize global loggers.
871
 *
872
 * Note that this is called very early in the process lifetime, so you should be
873
 * careful about what global state you rely on here.
874
 */
875
void InitLogging(const ArgsManager& args)
876
1.83k
{
877
1.83k
    init::SetLoggingOptions(args);
878
1.83k
    init::LogPackageVersion();
879
1.83k
}
880
881
namespace { // Variables internal to initialization process only
882
883
int nMaxConnections;
884
int available_fds;
885
ServiceFlags g_local_services = ServiceFlags(NODE_NETWORK_LIMITED | NODE_WITNESS);
886
int64_t peer_connect_timeout;
887
std::set<BlockFilterType> g_enabled_filter_types;
888
889
} // namespace
890
891
[[noreturn]] static void new_handler_terminate()
892
0
{
893
    // Rather than throwing std::bad-alloc if allocation fails, terminate
894
    // immediately to (try to) avoid chain corruption.
895
    // Since logging may itself allocate memory, set the handler directly
896
    // to terminate first.
897
0
    std::set_new_handler(std::terminate);
898
0
    LogError("Out of memory. Terminating.\n");
899
900
    // The log was successful, terminate now.
901
0
    std::terminate();
902
0
};
903
904
bool AppInitBasicSetup(const ArgsManager& args, std::atomic<int>& exit_status)
905
1.15k
{
906
    // ********************************************************* Step 1: setup
907
#ifdef _MSC_VER
908
    // Turn off Microsoft heap dump noise
909
    _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
910
    _CrtSetReportFile(_CRT_WARN, CreateFileA("NUL", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, 0));
911
    // Disable confusing "helpful" text message on abort, Ctrl-C
912
    _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
913
#endif
914
#ifdef WIN32
915
    // Enable heap terminate-on-corruption
916
    HeapSetInformation(nullptr, HeapEnableTerminationOnCorruption, nullptr, 0);
917
#endif
918
1.15k
    if (!SetupNetworking()) {
919
0
        return InitError(Untranslated("Initializing networking failed."));
920
0
    }
921
922
1.15k
#ifndef WIN32
923
    // Clean shutdown on SIGTERM
924
1.15k
    registerSignalHandler(SIGTERM, HandleSIGTERM);
925
1.15k
    registerSignalHandler(SIGINT, HandleSIGTERM);
926
927
    // Reopen debug.log on SIGHUP
928
1.15k
    registerSignalHandler(SIGHUP, HandleSIGHUP);
929
930
    // Ignore SIGPIPE, otherwise it will bring the daemon down if the client closes unexpectedly
931
1.15k
    signal(SIGPIPE, SIG_IGN);
932
#else
933
    SetConsoleCtrlHandler(consoleCtrlHandler, true);
934
#endif
935
936
1.15k
    std::set_new_handler(new_handler_terminate);
937
938
1.15k
    return true;
939
1.15k
}
940
941
bool AppInitParameterInteraction(const ArgsManager& args)
942
3.65k
{
943
3.65k
    const CChainParams& chainparams = Params();
944
    // ********************************************************* Step 2: parameter interactions
945
946
    // also see: InitParameterInteraction()
947
948
    // We removed checkpoints but keep the option to warn users who still have it in their config.
949
3.65k
    if (args.IsArgSet("-checkpoints")) {
950
0
        InitWarning(_("Option '-checkpoints' is set but checkpoints were removed. This option has no effect."));
951
0
    }
952
3.65k
    if (args.IsArgSet("-limitancestorsize")) {
953
0
        InitWarning(_("Option '-limitancestorsize' is given but ancestor size limits have been replaced with cluster size limits (see -limitclustersize). This option has no effect."));
954
0
    }
955
3.65k
    if (args.IsArgSet("-limitdescendantsize")) {
956
0
        InitWarning(_("Option '-limitdescendantsize' is given but descendant size limits have been replaced with cluster size limits (see -limitclustersize). This option has no effect."));
957
0
    }
958
959
    // Error if network-specific options (-addnode, -connect, etc) are
960
    // specified in default section of config file, but not overridden
961
    // on the command line or in this chain's section of the config file.
962
3.65k
    ChainType chain = args.GetChainType();
963
3.65k
    if (chain == ChainType::SIGNET) {
964
13
        LogInfo("Signet derived magic (message start): %s", HexStr(chainparams.MessageStart()));
965
13
    }
966
3.65k
    bilingual_str errors;
967
3.65k
    for (const auto& arg : args.GetUnsuitableSectionOnlyArgs()) {
968
1
        errors += strprintf(_("Config setting for %s only applied on %s network when in [%s] section."), arg, ChainTypeToString(chain), ChainTypeToString(chain)) + Untranslated("\n");
969
1
    }
970
971
3.65k
    if (!errors.empty()) {
972
1
        return InitError(errors);
973
1
    }
974
975
    // Testnet3 deprecation warning
976
3.65k
    if (chain == ChainType::TESTNET) {
977
2
        LogInfo("Warning: Support for testnet3 is deprecated and will be removed in an upcoming release. Consider switching to testnet4.\n");
978
2
    }
979
980
    // Warn if unrecognized section name are present in the config file.
981
3.65k
    bilingual_str warnings;
982
3.65k
    for (const auto& section : args.GetUnrecognizedSections()) {
983
2
        warnings += Untranslated(strprintf("%s:%i ", section.m_file, section.m_line)) + strprintf(_("Section [%s] is not recognized."), section.m_name) + Untranslated("\n");
984
2
    }
985
986
3.65k
    if (!warnings.empty()) {
987
1
        InitWarning(warnings);
988
1
    }
989
990
3.65k
    if (!fs::is_directory(args.GetBlocksDirPath())) {
991
1
        return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist."), args.GetArg("-blocksdir", "")));
992
1
    }
993
994
    // parse and validate enabled filter types
995
3.65k
    std::string blockfilterindex_value = args.GetArg("-blockfilterindex", DEFAULT_BLOCKFILTERINDEX);
996
3.65k
    if (blockfilterindex_value == "" || blockfilterindex_value == "1") {
997
49
        g_enabled_filter_types = AllBlockFilterTypes();
998
3.60k
    } else if (blockfilterindex_value != "0") {
999
1
        const std::vector<std::string> names = args.GetArgs("-blockfilterindex");
1000
1
        for (const auto& name : names) {
1001
1
            BlockFilterType filter_type;
1002
1
            if (!BlockFilterTypeByName(name, filter_type)) {
1003
1
                return InitError(strprintf(_("Unknown -blockfilterindex value %s."), name));
1004
1
            }
1005
0
            g_enabled_filter_types.insert(filter_type);
1006
0
        }
1007
1
    }
1008
1009
    // Signal NODE_P2P_V2 if BIP324 v2 transport is enabled.
1010
3.65k
    if (args.GetBoolArg("-v2transport", DEFAULT_V2_TRANSPORT)) {
1011
739
        g_local_services = ServiceFlags(g_local_services | NODE_P2P_V2);
1012
739
    }
1013
1014
    // Signal NODE_COMPACT_FILTERS if peerblockfilters and basic filters index are both enabled.
1015
3.65k
    if (args.GetBoolArg("-peerblockfilters", DEFAULT_PEERBLOCKFILTERS)) {
1016
2
        if (!g_enabled_filter_types.contains(BlockFilterType::BASIC)) {
1017
1
            return InitError(_("Cannot set -peerblockfilters without -blockfilterindex."));
1018
1
        }
1019
1020
1
        g_local_services = ServiceFlags(g_local_services | NODE_COMPACT_FILTERS);
1021
1
    }
1022
1023
3.65k
    if (args.GetIntArg("-prune", 0)) {
1024
43
        if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX))
1025
0
            return InitError(_("Prune mode is incompatible with -txindex."));
1026
43
        if (args.GetBoolArg("-txospenderindex", DEFAULT_TXOSPENDERINDEX))
1027
0
            return InitError(_("Prune mode is incompatible with -txospenderindex."));
1028
43
        if (args.GetBoolArg("-reindex-chainstate", false)) {
1029
0
            return InitError(_("Prune mode is incompatible with -reindex-chainstate. Use full -reindex instead."));
1030
0
        }
1031
43
    }
1032
1033
    // If -forcednsseed is set to true, ensure -dnsseed has not been set to false
1034
3.65k
    if (args.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED) && !args.GetBoolArg("-dnsseed", DEFAULT_DNSSEED)){
1035
2
        return InitError(_("Cannot set -forcednsseed to true when setting -dnsseed to false."));
1036
2
    }
1037
1038
    // -bind and -whitebind can't be set when not listening
1039
3.65k
    size_t nUserBind = args.GetArgs("-bind").size() + args.GetArgs("-whitebind").size();
1040
3.65k
    if (nUserBind != 0 && !args.GetBoolArg("-listen", DEFAULT_LISTEN)) {
1041
1
        return InitError(Untranslated("Cannot set -bind or -whitebind together with -listen=0"));
1042
1
    }
1043
1044
    // if listen=0, then disallow listenonion=1
1045
3.65k
    if (!args.GetBoolArg("-listen", DEFAULT_LISTEN) && args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) {
1046
0
        return InitError(Untranslated("Cannot set -listen=0 together with -listenonion=1"));
1047
0
    }
1048
1049
    // Make sure enough file descriptors are available. We need to reserve enough FDs to account for the bare minimum,
1050
    // plus all manual connections and all bound interfaces. Any remainder will be available for connection sockets
1051
1052
    // Number of bound interfaces (we have at least one)
1053
3.65k
    int nBind = std::max(nUserBind, size_t(1));
1054
    // Maximum number of connections with other nodes, this accounts for all types of outbounds and inbounds except for manual
1055
3.65k
    int user_max_connection = args.GetIntArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS);
1056
3.65k
    if (user_max_connection < 0) {
1057
0
        return InitError(Untranslated("-maxconnections must be greater or equal than zero"));
1058
0
    }
1059
3.65k
    const size_t max_private{args.GetBoolArg("-privatebroadcast", DEFAULT_PRIVATE_BROADCAST)
1060
3.65k
                             ? MAX_PRIVATE_BROADCAST_CONNECTIONS
1061
3.65k
                             : 0};
1062
    // Reserve enough FDs to account for the bare minimum, plus any manual connections, plus the bound interfaces
1063
3.65k
    int min_required_fds = MIN_CORE_FDS + MAX_ADDNODE_CONNECTIONS + nBind;
1064
1065
    // Try raising the FD limit to what we need (available_fds may be smaller than the requested amount if this fails)
1066
3.65k
    available_fds = RaiseFileDescriptorLimit(user_max_connection + max_private + min_required_fds);
1067
    // If we are using select instead of poll, our actual limit may be even smaller
1068
#ifndef USE_POLL
1069
    available_fds = std::min(FD_SETSIZE, available_fds);
1070
#endif
1071
3.65k
    if (available_fds < min_required_fds)
1072
0
        return InitError(strprintf(_("Not enough file descriptors available. %d available, %d required."), available_fds, min_required_fds));
1073
1074
    // Trim requested connection counts, to fit into system limitations
1075
3.65k
    nMaxConnections = std::min(available_fds - min_required_fds, user_max_connection);
1076
1077
3.65k
    if (nMaxConnections < user_max_connection)
1078
0
        InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations."), user_max_connection, nMaxConnections));
1079
1080
    // ********************************************************* Step 3: parameter-to-internal-flags
1081
3.65k
    if (auto result{init::SetLoggingCategories(args)}; !result) return InitError(util::ErrorString(result));
1082
3.65k
    if (auto result{init::SetLoggingLevel(args)}; !result) return InitError(util::ErrorString(result));
1083
1084
3.64k
    nConnectTimeout = args.GetIntArg("-timeout", DEFAULT_CONNECT_TIMEOUT);
1085
3.64k
    if (nConnectTimeout <= 0) {
1086
0
        nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
1087
0
    }
1088
1089
3.64k
    peer_connect_timeout = args.GetIntArg("-peertimeout", DEFAULT_PEER_CONNECT_TIMEOUT);
1090
3.64k
    if (peer_connect_timeout <= 0) {
1091
2
        return InitError(Untranslated("peertimeout must be a positive integer."));
1092
2
    }
1093
1094
3.64k
    auto mining_result{node::ReadMiningArgs(args)};
1095
3.64k
    if (!mining_result) {
1096
4
        return InitError(util::ErrorString(mining_result));
1097
4
    }
1098
1099
3.64k
    nBytesPerSigOp = args.GetIntArg("-bytespersigop", nBytesPerSigOp);
1100
1101
3.64k
    if (!g_wallet_init_interface.ParameterInteraction()) return false;
1102
1103
    // Option to startup with mocktime set (used for regression testing):
1104
3.64k
    if (const auto mocktime{args.GetIntArg("-mocktime")}) {
1105
11
        SetMockTime(std::chrono::seconds{*mocktime});
1106
11
    }
1107
1108
3.64k
    if (args.GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS))
1109
3
        g_local_services = ServiceFlags(g_local_services | NODE_BLOOM);
1110
1111
3.64k
    const std::vector<std::string> test_options = args.GetArgs("-test");
1112
3.64k
    if (!test_options.empty()) {
1113
15
        if (chainparams.GetChainType() != ChainType::REGTEST) {
1114
0
            return InitError(Untranslated("-test=<option> can only be used with regtest"));
1115
0
        }
1116
15
        for (const std::string& option : test_options) {
1117
18
            auto it = std::find_if(TEST_OPTIONS_DOC.begin(), TEST_OPTIONS_DOC.end(), [&option](const std::string& doc_option) {
1118
18
                size_t pos = doc_option.find(" (");
1119
18
                return (pos != std::string::npos) && (doc_option.substr(0, pos) == option);
1120
18
            });
1121
15
            if (it == TEST_OPTIONS_DOC.end()) {
1122
0
                InitWarning(strprintf(_("Unrecognised option \"%s\" provided in -test=<option>."), option));
1123
0
            }
1124
15
        }
1125
15
    }
1126
1127
    // Prevent setting deployment parameters on mainnet.
1128
3.64k
    if (chainparams.GetChainType() == ChainType::MAIN) {
1129
585
        if (args.IsArgSet("-testactivationheight")) {
1130
0
            return InitError(_("The -testactivationheight option may not be used on mainnet."));
1131
0
        }
1132
585
        if (args.IsArgSet("-vbparams")) {
1133
0
            return InitError(_("The -vbparams option may not be used on mainnet."));
1134
0
        }
1135
585
    }
1136
1137
    // Also report errors from parsing before daemonization
1138
3.64k
    {
1139
3.64k
        kernel::Notifications notifications{};
1140
3.64k
        ChainstateManager::Options chainman_opts_dummy{
1141
3.64k
            .chainparams = chainparams,
1142
3.64k
            .datadir = args.GetDataDirNet(),
1143
3.64k
            .notifications = notifications,
1144
3.64k
        };
1145
3.64k
        auto chainman_result{ApplyArgsManOptions(args, chainman_opts_dummy)};
1146
3.64k
        if (!chainman_result) {
1147
1
            return InitError(util::ErrorString(chainman_result));
1148
1
        }
1149
3.64k
        BlockManager::Options blockman_opts_dummy{
1150
3.64k
            .chainparams = chainman_opts_dummy.chainparams,
1151
3.64k
            .blocks_dir = args.GetBlocksDirPath(),
1152
3.64k
            .notifications = chainman_opts_dummy.notifications,
1153
3.64k
            .block_tree_db_params = DBParams{
1154
3.64k
                .path = args.GetDataDirNet() / "blocks" / "index",
1155
3.64k
                .cache_bytes = 0,
1156
3.64k
            },
1157
3.64k
        };
1158
3.64k
        auto blockman_result{ApplyArgsManOptions(args, blockman_opts_dummy)};
1159
3.64k
        if (!blockman_result) {
1160
0
            return InitError(util::ErrorString(blockman_result));
1161
0
        }
1162
3.64k
        CTxMemPool::Options mempool_opts{};
1163
3.64k
        auto mempool_result{ApplyArgsManOptions(args, chainparams, mempool_opts)};
1164
3.64k
        if (!mempool_result) {
1165
1
            return InitError(util::ErrorString(mempool_result));
1166
1
        }
1167
3.64k
    }
1168
1169
3.63k
    return true;
1170
3.64k
}
1171
1172
static bool LockDirectory(const fs::path& dir, bool probeOnly)
1173
4.54k
{
1174
    // Make sure only a single process is using the directory.
1175
4.54k
    switch (util::LockDirectory(dir, ".lock", probeOnly)) {
1176
0
    case util::LockResult::ErrorWrite:
1177
0
        return InitError(strprintf(_("Cannot write to directory '%s'; check permissions."), fs::PathToString(dir)));
1178
2
    case util::LockResult::ErrorLock:
1179
2
        return InitError(strprintf(_("Cannot obtain a lock on directory %s. %s is probably already running."), fs::PathToString(dir), CLIENT_NAME));
1180
4.54k
    case util::LockResult::Success: return true;
1181
4.54k
    } // no default case, so the compiler can warn about missing cases
1182
4.54k
    assert(false);
1183
0
}
1184
static bool LockDirectories(bool probeOnly)
1185
2.27k
{
1186
2.27k
    return LockDirectory(gArgs.GetDataDirNet(), probeOnly) && \
1187
2.27k
           LockDirectory(gArgs.GetBlocksDirPath(), probeOnly);
1188
2.27k
}
1189
1190
bool AppInitSanityChecks(const kernel::Context& kernel)
1191
1.13k
{
1192
    // ********************************************************* Step 4: sanity checks
1193
1.13k
    auto result{kernel::SanityChecks(kernel)};
1194
1.13k
    if (!result) {
1195
0
        InitError(util::ErrorString(result));
1196
0
        return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), CLIENT_NAME));
1197
0
    }
1198
1199
1.13k
    if (!ECC_InitSanityCheck()) {
1200
0
        return InitError(strprintf(_("Elliptic curve cryptography sanity check failure. %s is shutting down."), CLIENT_NAME));
1201
0
    }
1202
1203
    // Probe the directory locks to give an early error message, if possible
1204
    // We cannot hold the directory locks here, as the forking for daemon() hasn't yet happened,
1205
    // and a fork will cause weird behavior to them.
1206
1.13k
    return LockDirectories(true);
1207
1.13k
}
1208
1209
bool AppInitLockDirectories()
1210
1.13k
{
1211
    // After daemonization get the directory locks again and hold on to them until exit
1212
    // This creates a slight window for a race condition to happen, however this condition is harmless: it
1213
    // will at most make us exit without printing a message to console.
1214
1.13k
    if (!LockDirectories(false)) {
1215
        // Detailed error printed inside LockDirectory
1216
0
        return false;
1217
0
    }
1218
1.13k
    return true;
1219
1.13k
}
1220
1221
bool AppInitInterfaces(NodeContext& node)
1222
1.13k
{
1223
1.13k
    node.chain = interfaces::MakeChain(node);
1224
    // Specify wait_loaded=false so internal mining interface can be initialized
1225
    // on early startup and does not need to be tied to chainstate loading.
1226
1.13k
    node.mining = interfaces::MakeMining(node, /*wait_loaded=*/false);
1227
1.13k
    return true;
1228
1.13k
}
1229
1230
1.13k
bool CheckHostPortOptions(const ArgsManager& args) {
1231
1.13k
    for (const std::string port_option : {
1232
1.13k
        "-port",
1233
1.13k
        "-rpcport",
1234
2.26k
    }) {
1235
2.26k
        if (const auto port{args.GetArg(port_option)}) {
1236
2.26k
            const auto n{ToIntegral<uint16_t>(*port)};
1237
2.26k
            if (!n || *n == 0) {
1238
2
                return InitError(InvalidPortErrMsg(port_option, *port));
1239
2
            }
1240
2.26k
        }
1241
2.26k
    }
1242
1243
1.13k
    for ([[maybe_unused]] const auto& [param_name, unix, suffix_allowed] : std::vector<std::tuple<std::string, bool, bool>>{
1244
        // arg name          UNIX socket support  =suffix allowed
1245
1.13k
        {"-i2psam",          false,               false},
1246
1.13k
        {"-onion",           true,                false},
1247
1.13k
        {"-proxy",           true,                true},
1248
1.13k
        {"-bind",            false,               true},
1249
1.13k
        {"-rpcbind",         false,               false},
1250
1.13k
        {"-torcontrol",      false,               false},
1251
1.13k
        {"-whitebind",       false,               false},
1252
1.13k
        {"-zmqpubhashblock", true,                false},
1253
1.13k
        {"-zmqpubhashtx",    true,                false},
1254
1.13k
        {"-zmqpubrawblock",  true,                false},
1255
1.13k
        {"-zmqpubrawtx",     true,                false},
1256
1.13k
        {"-zmqpubsequence",  true,                false},
1257
13.4k
    }) {
1258
13.4k
        for (const std::string& param_value : args.GetArgs(param_name)) {
1259
1.21k
            const std::string param_value_hostport{
1260
1.21k
                suffix_allowed ? param_value.substr(0, param_value.rfind('=')) : param_value};
1261
1.21k
            std::string host_out;
1262
1.21k
            uint16_t port_out{0};
1263
1.21k
            if (!SplitHostPort(param_value_hostport, port_out, host_out)) {
1264
14
#ifdef HAVE_SOCKADDR_UN
1265
                // Allow unix domain sockets for some options e.g. unix:/some/file/path
1266
14
                if (!unix || !param_value.starts_with(ADDR_PREFIX_UNIX)) {
1267
11
                    return InitError(InvalidPortErrMsg(param_name, param_value));
1268
11
                }
1269
#else
1270
                return InitError(InvalidPortErrMsg(param_name, param_value));
1271
#endif
1272
14
            }
1273
1.21k
        }
1274
13.4k
    }
1275
1276
1.12k
    return true;
1277
1.13k
}
1278
1279
/**
1280
 * @brief Checks for duplicate bindings across all binding configurations.
1281
 *
1282
 * @param[in] conn_options Connection options containing the binding vectors to check
1283
 * @return std::optional<CService> containing the first duplicate found, or std::nullopt if no duplicates
1284
 */
1285
static std::optional<CService> CheckBindingConflicts(const CConnman::Options& conn_options)
1286
1.01k
{
1287
1.01k
    std::set<CService> seen;
1288
1289
    // Check all whitelisted bindings
1290
1.01k
    for (const auto& wb : conn_options.vWhiteBinds) {
1291
8
        if (!seen.insert(wb.m_service).second) {
1292
1
            return wb.m_service;
1293
1
        }
1294
8
    }
1295
1296
    // Check regular bindings
1297
1.01k
    for (const auto& bind : conn_options.vBinds) {
1298
984
        if (!seen.insert(bind).second) {
1299
2
            return bind;
1300
2
        }
1301
984
    }
1302
1303
    // Check onion bindings
1304
1.01k
    for (const auto& onion_bind : conn_options.onion_binds) {
1305
44
        if (!seen.insert(onion_bind).second) {
1306
3
            return onion_bind;
1307
3
        }
1308
44
    }
1309
1310
1.00k
    return std::nullopt;
1311
1.01k
}
1312
1313
// A GUI user may opt to retry once with do_reindex set if there is a failure during chainstate initialization.
1314
// The function therefore has to support re-entry.
1315
static ChainstateLoadResult InitAndLoadChainstate(
1316
    NodeContext& node,
1317
    bool do_reindex,
1318
    const bool do_reindex_chainstate,
1319
    const kernel::CacheSizes& cache_sizes,
1320
    const ArgsManager& args)
1321
2.10k
{
1322
    // This function may be called twice, so any dirty state must be reset.
1323
2.10k
    node.notifications->setChainstateLoaded(false); // Drop state, such as a cached tip block
1324
2.10k
    node.mempool.reset();
1325
2.10k
    node.chainman.reset(); // Drop state, such as an initialized m_block_tree_db
1326
1327
2.10k
    const CChainParams& chainparams = Params();
1328
1329
2.10k
    CTxMemPool::Options mempool_opts{
1330
2.10k
        .check_ratio = chainparams.DefaultConsistencyChecks() ? 1 : 0,
1331
2.10k
        .signals = node.validation_signals.get(),
1332
2.10k
    };
1333
2.10k
    Assert(ApplyArgsManOptions(args, chainparams, mempool_opts)); // no error can happen, already checked in AppInitParameterInteraction
1334
2.10k
    bilingual_str mempool_error;
1335
2.10k
    Assert(!node.mempool); // Was reset above
1336
2.10k
    node.mempool = std::make_unique<CTxMemPool>(mempool_opts, mempool_error);
1337
2.10k
    if (!mempool_error.empty()) {
1338
1
        return {ChainstateLoadStatus::FAILURE_FATAL, mempool_error};
1339
1
    }
1340
2.10k
    auto mining_args{node::ReadMiningArgs(args)};
1341
2.10k
    Assert(mining_args); // no error can happen, already checked in AppInitParameterInteraction
1342
2.10k
    node.mining_args = std::move(*mining_args);
1343
2.10k
    LogInfo("* Using %.1f MiB for in-memory UTXO set (plus up to %.1f MiB of unused mempool space)",
1344
2.10k
            cache_sizes.coins / double(1_MiB),
1345
2.10k
            mempool_opts.max_size_bytes / double(1_MiB));
1346
2.10k
    ChainstateManager::Options chainman_opts{
1347
2.10k
        .chainparams = chainparams,
1348
2.10k
        .datadir = args.GetDataDirNet(),
1349
2.10k
        .notifications = *node.notifications,
1350
2.10k
        .signals = node.validation_signals.get(),
1351
2.10k
    };
1352
2.10k
    Assert(ApplyArgsManOptions(args, chainman_opts)); // no error can happen, already checked in AppInitParameterInteraction
1353
1354
2.10k
    BlockManager::Options blockman_opts{
1355
2.10k
        .chainparams = chainman_opts.chainparams,
1356
2.10k
        .blocks_dir = args.GetBlocksDirPath(),
1357
2.10k
        .notifications = chainman_opts.notifications,
1358
2.10k
        .block_tree_db_params = DBParams{
1359
2.10k
            .path = args.GetDataDirNet() / "blocks" / "index",
1360
2.10k
            .cache_bytes = cache_sizes.block_tree_db,
1361
2.10k
            .wipe_data = do_reindex,
1362
2.10k
        },
1363
2.10k
    };
1364
2.10k
    Assert(ApplyArgsManOptions(args, blockman_opts)); // no error can happen, already checked in AppInitParameterInteraction
1365
1366
    // Creating the chainstate manager internally creates a BlockManager, opens
1367
    // the blocks tree db, and wipes existing block files in case of a reindex.
1368
    // The coinsdb is opened at a later point on LoadChainstate.
1369
2.10k
    Assert(!node.chainman); // Was reset above
1370
2.10k
    try {
1371
2.10k
        node.chainman = std::make_unique<ChainstateManager>(*Assert(node.shutdown_signal), chainman_opts, blockman_opts);
1372
2.10k
    } catch (dbwrapper_error& e) {
1373
1
        LogError("%s", e.what());
1374
1
        return {ChainstateLoadStatus::FAILURE, _("Error opening block database")};
1375
1
    } catch (std::exception& e) {
1376
1
        return {ChainstateLoadStatus::FAILURE_FATAL, Untranslated(strprintf("Failed to initialize ChainstateManager: %s", e.what()))};
1377
1
    }
1378
1.04k
    ChainstateManager& chainman = *node.chainman;
1379
1.04k
    if (chainman.m_interrupt) return {ChainstateLoadStatus::INTERRUPTED, {}};
1380
1381
    // This is defined and set here instead of inline in validation.h to avoid a hard
1382
    // dependency between validation and index/base, since the latter is not in
1383
    // libbitcoinkernel.
1384
1.04k
    chainman.snapshot_download_completed = [&node]() {
1385
7
        if (!node.chainman->m_blockman.IsPruneMode()) {
1386
5
            LogInfo("[snapshot] re-enabling NODE_NETWORK services");
1387
5
            node.connman->AddLocalServices(NODE_NETWORK);
1388
5
        }
1389
7
        LogInfo("[snapshot] restarting indexes");
1390
        // Drain the validation interface queue to ensure that the old indexes
1391
        // don't have any pending work.
1392
7
        Assert(node.validation_signals)->SyncWithValidationInterfaceQueue();
1393
8
        for (auto* index : node.indexes) {
1394
8
            index->Interrupt();
1395
8
            index->Stop();
1396
8
            if (!(index->Init() && index->StartBackgroundSync())) {
1397
0
                LogWarning("[snapshot] Failed to restart index %s on snapshot chain", index->GetName());
1398
0
            }
1399
8
        }
1400
7
    };
1401
1.04k
    node::ChainstateLoadOptions options;
1402
1.04k
    options.mempool = Assert(node.mempool.get());
1403
1.04k
    options.wipe_chainstate_db = do_reindex || do_reindex_chainstate;
1404
1.04k
    options.prune = chainman.m_blockman.IsPruneMode();
1405
1.04k
    options.check_blocks = args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS);
1406
1.04k
    options.check_level = args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL);
1407
1.04k
    options.require_full_verification = args.IsArgSet("-checkblocks") || args.IsArgSet("-checklevel");
1408
1.04k
    options.coins_error_cb = [] {
1409
0
        uiInterface.ThreadSafeMessageBox(
1410
0
            _("Error reading from database, shutting down."),
1411
0
            CClientUIInterface::MSG_ERROR);
1412
0
    };
1413
1.04k
    uiInterface.InitMessage(_("Loading block index…"));
1414
2.07k
    auto catch_exceptions = [](auto&& f) -> ChainstateLoadResult {
1415
2.07k
        try {
1416
2.07k
            return f();
1417
2.07k
        } catch (const std::exception& e) {
1418
0
            LogError("%s\n", e.what());
1419
0
            return std::make_tuple(node::ChainstateLoadStatus::FAILURE, _("Error loading databases"));
1420
0
        }
1421
2.07k
    };
init.cpp:_ZZL21InitAndLoadChainstateRN4node11NodeContextEbbRKN6kernel10CacheSizesERK11ArgsManagerENK3$_2clIZL21InitAndLoadChainstateS1_bbS5_S8_E3$_3EESt5tupleIJNS_20ChainstateLoadStatusE13bilingual_strEEOT_
Line
Count
Source
1414
1.04k
    auto catch_exceptions = [](auto&& f) -> ChainstateLoadResult {
1415
1.04k
        try {
1416
1.04k
            return f();
1417
1.04k
        } catch (const std::exception& e) {
1418
0
            LogError("%s\n", e.what());
1419
0
            return std::make_tuple(node::ChainstateLoadStatus::FAILURE, _("Error loading databases"));
1420
0
        }
1421
1.04k
    };
init.cpp:_ZZL21InitAndLoadChainstateRN4node11NodeContextEbbRKN6kernel10CacheSizesERK11ArgsManagerENK3$_2clIZL21InitAndLoadChainstateS1_bbS5_S8_E3$_4EESt5tupleIJNS_20ChainstateLoadStatusE13bilingual_strEEOT_
Line
Count
Source
1414
1.03k
    auto catch_exceptions = [](auto&& f) -> ChainstateLoadResult {
1415
1.03k
        try {
1416
1.03k
            return f();
1417
1.03k
        } catch (const std::exception& e) {
1418
0
            LogError("%s\n", e.what());
1419
0
            return std::make_tuple(node::ChainstateLoadStatus::FAILURE, _("Error loading databases"));
1420
0
        }
1421
1.03k
    };
1422
1.04k
    auto [status, error] = catch_exceptions([&] { return LoadChainstate(chainman, cache_sizes, options); });
1423
1.04k
    if (status == node::ChainstateLoadStatus::SUCCESS) {
1424
1.03k
        uiInterface.InitMessage(_("Verifying blocks…"));
1425
1.03k
        if (chainman.m_blockman.m_have_pruned && options.check_blocks > MIN_BLOCKS_TO_KEEP) {
1426
0
            LogWarning("pruned datadir may not have more than %d blocks; only checking available blocks\n",
1427
0
                       MIN_BLOCKS_TO_KEEP);
1428
0
        }
1429
1.03k
        std::tie(status, error) = catch_exceptions([&] { return VerifyLoadedChainstate(chainman, options); });
1430
1.03k
        if (status == node::ChainstateLoadStatus::SUCCESS) {
1431
1.02k
            LogInfo("Block index and chainstate loaded");
1432
1.02k
            node.notifications->setChainstateLoaded(true);
1433
1.02k
        }
1434
1.03k
    }
1435
1.04k
    return {status, error};
1436
1.04k
};
1437
1438
bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
1439
1.13k
{
1440
1.13k
    const ArgsManager& args = *Assert(node.args);
1441
1.13k
    const CChainParams& chainparams = Params();
1442
1443
1.13k
    auto opt_max_upload = ParseByteUnits(args.GetArg("-maxuploadtarget", DEFAULT_MAX_UPLOAD_TARGET), ByteUnit::M);
1444
1.13k
    if (!opt_max_upload) {
1445
1
        return InitError(strprintf(_("Unable to parse -maxuploadtarget: '%s'"), args.GetArg("-maxuploadtarget", "")));
1446
1
    }
1447
1448
    // ********************************************************* Step 4a: application initialization
1449
1.13k
    if (!CreatePidFile(args)) {
1450
        // Detailed error printed inside CreatePidFile().
1451
0
        return false;
1452
0
    }
1453
1.13k
    if (!init::StartLogging(args)) {
1454
        // Detailed error printed inside StartLogging().
1455
2
        return false;
1456
2
    }
1457
1458
1.13k
    LogInfo("Using at most %i automatic connections (%i file descriptors available)", nMaxConnections, available_fds);
1459
1460
    // Warn about relative -datadir path.
1461
1.13k
    if (args.IsArgSet("-datadir") && !args.GetPathArg("-datadir").is_absolute()) {
1462
0
        LogWarning("Relative datadir option '%s' specified, which will be interpreted relative to the "
1463
0
                   "current working directory '%s'. This is fragile, because if bitcoin is started in the future "
1464
0
                   "from a different location, it will be unable to locate the current data files. There could "
1465
0
                   "also be data loss if bitcoin is started while in a temporary directory.",
1466
0
                   args.GetArg("-datadir", ""), fs::PathToString(fs::current_path()));
1467
0
    }
1468
1469
1.13k
    assert(!node.scheduler);
1470
1.13k
    node.scheduler = std::make_unique<CScheduler>();
1471
1.13k
    auto& scheduler = *node.scheduler;
1472
1473
    // Start the lightweight task scheduler thread
1474
1.13k
    scheduler.m_service_thread = std::thread(util::TraceThread, "scheduler", [&] { scheduler.serviceQueue(); });
1475
1476
    // Gather some entropy once per minute.
1477
1.13k
    scheduler.scheduleEvery([]{
1478
84
        RandAddPeriodic();
1479
84
    }, std::chrono::minutes{1});
1480
1481
    // Check disk space every 5 minutes to avoid db corruption.
1482
1.13k
    scheduler.scheduleEvery([&args, &node]{
1483
13
        constexpr uint64_t min_disk_space{50_MiB};
1484
13
        if (!CheckDiskSpace(args.GetBlocksDirPath(), min_disk_space)) {
1485
0
            LogError("Shutting down due to lack of disk space!\n");
1486
0
            if (!(Assert(node.shutdown_request))()) {
1487
0
                LogError("Failed to send shutdown signal after disk space check\n");
1488
0
            }
1489
0
        }
1490
13
    }, std::chrono::minutes{5});
1491
1492
1.13k
    if (args.GetBoolArg("-logratelimit", BCLog::DEFAULT_LOGRATELIMIT)) {
1493
1
        LogInstance().SetRateLimiting(BCLog::LogRateLimiter::Create(
1494
1
            [&scheduler](auto func, auto window) { scheduler.scheduleEvery(std::move(func), window); },
1495
1
            BCLog::RATELIMIT_MAX_BYTES,
1496
1
            BCLog::RATELIMIT_WINDOW));
1497
1.13k
    } else {
1498
1.13k
        LogInfo("Log rate limiting disabled");
1499
1.13k
    }
1500
1501
1.13k
    assert(!node.validation_signals);
1502
1.13k
    node.validation_signals = std::make_unique<ValidationSignals>(std::make_unique<SerialTaskRunner>(scheduler));
1503
1.13k
    auto& validation_signals = *node.validation_signals;
1504
1505
    // Create KernelNotifications object. Important to do this early before
1506
    // calling ipc->listenAddress() below so makeMining and other IPC methods
1507
    // can use this.
1508
1.13k
    assert(!node.notifications);
1509
1.13k
    node.notifications = std::make_unique<KernelNotifications>(Assert(node.shutdown_request), node.exit_status, *Assert(node.warnings));
1510
1.13k
    ReadNotificationArgs(args, *node.notifications);
1511
1512
    // Create client interfaces for wallets that are supposed to be loaded
1513
    // according to -wallet and -disablewallet options. This only constructs
1514
    // the interfaces, it doesn't load wallet data. Wallets actually get loaded
1515
    // when load() and start() interface methods are called below.
1516
1.13k
    g_wallet_init_interface.Construct(node);
1517
1.13k
    uiInterface.InitWallet();
1518
1519
1.13k
    if (interfaces::Ipc* ipc = node.init->ipc()) {
1520
1
        for (std::string address : gArgs.GetArgs("-ipcbind")) {
1521
1
            try {
1522
1
                ipc->listenAddress(address);
1523
1
            } catch (const std::exception& e) {
1524
0
                return InitError(Untranslated(strprintf("Unable to bind to IPC address '%s'. %s", address, e.what())));
1525
0
            }
1526
1
            LogInfo("Listening for IPC requests on address %s", address);
1527
1
        }
1528
1
    }
1529
1530
    /* Register RPC commands regardless of -server setting so they will be
1531
     * available in the GUI RPC console even if external calls are disabled.
1532
     */
1533
1.13k
    RegisterAllCoreRPCCommands(tableRPC);
1534
1.13k
    for (const auto& client : node.chain_clients) {
1535
398
        client->registerRpcs();
1536
398
    }
1537
#ifdef ENABLE_ZMQ
1538
    RegisterZMQRPCCommands(tableRPC);
1539
#endif
1540
1541
    // Check port numbers
1542
1.13k
    if (!CheckHostPortOptions(args)) return false;
1543
1544
    // Configure reachable networks before we start the RPC server.
1545
    // This is necessary for -rpcallowip to distinguish CJDNS from other RFC4193
1546
1.12k
    const auto onlynets = args.GetArgs("-onlynet");
1547
1.12k
    if (!onlynets.empty()) {
1548
8
        g_reachable_nets.RemoveAll();
1549
8
        for (const std::string& snet : onlynets) {
1550
8
            enum Network net = ParseNetwork(snet);
1551
8
            if (net == NET_UNROUTABLE)
1552
1
                return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet));
1553
7
            g_reachable_nets.Add(net);
1554
7
        }
1555
8
    }
1556
1557
1.11k
    if (!args.IsArgSet("-cjdnsreachable")) {
1558
1.11k
        if (!onlynets.empty() && g_reachable_nets.Contains(NET_CJDNS)) {
1559
1
            return InitError(
1560
1
                _("Outbound connections restricted to CJDNS (-onlynet=cjdns) but "
1561
1
                  "-cjdnsreachable is not provided"));
1562
1
        }
1563
1.11k
        g_reachable_nets.Remove(NET_CJDNS);
1564
1.11k
    }
1565
    // Now g_reachable_nets.Contains(NET_CJDNS) is true if:
1566
    // 1. -cjdnsreachable is given and
1567
    // 2.1. -onlynet is not given or
1568
    // 2.2. -onlynet=cjdns is given
1569
1570
    /* Start the RPC server already.  It will be started in "warmup" mode
1571
     * and not really process calls already (but it will signify connections
1572
     * that the server is there and will be ready later).  Warmup mode will
1573
     * be disabled when initialisation is finished.
1574
     */
1575
1.11k
    if (args.GetBoolArg("-server", false)) {
1576
1.11k
        uiInterface.InitMessage.connect(SetRPCWarmupStatus);
1577
1.11k
        if (!AppInitServers(node))
1578
13
            return InitError(_("Unable to start HTTP server. See debug log for details."));
1579
1.11k
    }
1580
1581
    // ********************************************************* Step 5: verify wallet database integrity
1582
1.10k
    for (const auto& client : node.chain_clients) {
1583
398
        if (!client->verify()) {
1584
23
            return false;
1585
23
        }
1586
398
    }
1587
1588
    // ********************************************************* Step 6: network initialization
1589
    // Note that we absolutely cannot open any actual connections
1590
    // until the very end ("start node") as the UTXO/block state
1591
    // is not yet setup and may end up being set up twice if we
1592
    // need to reindex later.
1593
1594
1.08k
    fListen = args.GetBoolArg("-listen", DEFAULT_LISTEN);
1595
1.08k
    fDiscover = args.GetBoolArg("-discover", true);
1596
1597
1.08k
    PeerManager::Options peerman_opts{};
1598
1.08k
    ApplyArgsManOptions(args, peerman_opts);
1599
1600
1.08k
    {
1601
        // Read asmap file if configured or embedded asmap data and initialize
1602
        // Netgroupman with or without it
1603
1.08k
        assert(!node.netgroupman);
1604
1.08k
        if (args.IsArgSet("-asmap") && !args.IsArgNegated("-asmap")) {
1605
9
            uint256 asmap_version{};
1606
9
            if (!args.GetBoolArg("-asmap", false)) {
1607
7
                fs::path asmap_path = args.GetPathArg("-asmap");
1608
7
                if (!asmap_path.is_absolute()) {
1609
2
                    asmap_path = args.GetDataDirNet() / asmap_path;
1610
2
                }
1611
1612
                // If a specific path was passed with the asmap argument check if
1613
                // the file actually exists in that location
1614
7
                if (!fs::exists(asmap_path)) {
1615
1
                    InitError(strprintf(_("Could not find asmap file %s"), fs::quoted(fs::PathToString(asmap_path))));
1616
1
                    return false;
1617
1
                }
1618
1619
                // If a file exists at the path, try to read the file
1620
6
                std::vector<std::byte> asmap{DecodeAsmap(asmap_path)};
1621
6
                if (asmap.empty()) {
1622
1
                    InitError(strprintf(_("Could not parse asmap file %s"), fs::quoted(fs::PathToString(asmap_path))));
1623
1
                    return false;
1624
1
                }
1625
5
                asmap_version = AsmapVersion(asmap);
1626
5
                node.netgroupman = std::make_unique<NetGroupManager>(NetGroupManager::WithLoadedAsmap(std::move(asmap)));
1627
5
            } else {
1628
2
                #ifdef ENABLE_EMBEDDED_ASMAP
1629
                    // Use the embedded asmap data
1630
2
                    std::span<const std::byte> asmap{node::data::ip_asn};
1631
2
                    if (asmap.empty() || !CheckStandardAsmap(asmap)) {
1632
0
                        InitError(strprintf(_("Could not read embedded asmap data")));
1633
0
                        return false;
1634
0
                    }
1635
2
                    node.netgroupman = std::make_unique<NetGroupManager>(NetGroupManager::WithEmbeddedAsmap(asmap));
1636
2
                    asmap_version = AsmapVersion(asmap);
1637
2
                    LogInfo("Opened asmap data (%zu bytes) from embedded byte array\n", asmap.size());
1638
                #else
1639
                    // If there is no embedded data, fail and report it since
1640
                    // the user tried to use it
1641
                    InitError(strprintf(_("Embedded asmap data not available")));
1642
                    return false;
1643
                #endif
1644
2
            }
1645
7
            LogInfo("Using asmap version %s for IP bucketing", asmap_version.ToString());
1646
1.07k
        } else {
1647
1.07k
            node.netgroupman = std::make_unique<NetGroupManager>(NetGroupManager::NoAsmap());
1648
1.07k
            LogInfo("Using /16 prefix for IP bucketing");
1649
1.07k
        }
1650
1651
        // Initialize addrman
1652
1.08k
        assert(!node.addrman);
1653
1.08k
        uiInterface.InitMessage(_("Loading P2P addresses…"));
1654
1.08k
        auto addrman{LoadAddrman(*node.netgroupman, args)};
1655
1.08k
        if (!addrman) return InitError(util::ErrorString(addrman));
1656
1.07k
        node.addrman = std::move(*addrman);
1657
1.07k
    }
1658
1659
0
    FastRandomContext rng;
1660
1.07k
    assert(!node.banman);
1661
1.07k
    node.banman = std::make_unique<BanMan>(args.GetDataDirNet() / "banlist", &uiInterface, args.GetIntArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
1662
1.07k
    assert(!node.connman);
1663
1.07k
    node.connman = std::make_unique<CConnman>(rng.rand64(),
1664
1.07k
                                              rng.rand64(),
1665
1.07k
                                              *node.addrman, *node.netgroupman, chainparams, args.GetBoolArg("-networkactive", true));
1666
1667
1.07k
    assert(!node.fee_estimator);
1668
    // Don't initialize fee estimation with old data if we don't relay transactions,
1669
    // as they would never get updated.
1670
1.07k
    if (!peerman_opts.ignore_incoming_txs) {
1671
1.06k
        bool read_stale_estimates = args.GetBoolArg("-acceptstalefeeestimates", DEFAULT_ACCEPT_STALE_FEE_ESTIMATES);
1672
1.06k
        if (read_stale_estimates && (chainparams.GetChainType() != ChainType::REGTEST)) {
1673
4
            return InitError(strprintf(_("acceptstalefeeestimates is not supported on %s chain."), chainparams.GetChainTypeString()));
1674
4
        }
1675
1.06k
        node.fee_estimator = std::make_unique<CBlockPolicyEstimator>(FeeestPath(args), read_stale_estimates);
1676
1677
        // Flush estimates to disk periodically
1678
1.06k
        CBlockPolicyEstimator* fee_estimator = node.fee_estimator.get();
1679
1.06k
        scheduler.scheduleEvery([fee_estimator] { fee_estimator->FlushFeeEstimates(); }, FEE_FLUSH_INTERVAL);
1680
1.06k
        validation_signals.RegisterValidationInterface(fee_estimator);
1681
1.06k
    }
1682
1683
1.06k
    for (const std::string& socket_addr : args.GetArgs("-bind")) {
1684
1.06k
        std::string host_out;
1685
1.06k
        uint16_t port_out{0};
1686
1.06k
        std::string bind_socket_addr = socket_addr.substr(0, socket_addr.rfind('='));
1687
1.06k
        if (!SplitHostPort(bind_socket_addr, port_out, host_out)) {
1688
0
            return InitError(InvalidPortErrMsg("-bind", socket_addr));
1689
0
        }
1690
1.06k
    }
1691
1692
    // sanitize comments per BIP-0014, format user agent and check total size
1693
1.06k
    std::vector<std::string> uacomments;
1694
1.08k
    for (const std::string& cmt : args.GetArgs("-uacomment")) {
1695
1.08k
        if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT))
1696
6
            return InitError(strprintf(_("User Agent comment (%s) contains unsafe characters."), cmt));
1697
1.07k
        uacomments.push_back(cmt);
1698
1.07k
    }
1699
1.06k
    strSubVersion = FormatSubVersion(UA_NAME, CLIENT_VERSION, uacomments);
1700
1.06k
    if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) {
1701
1
        return InitError(strprintf(_("Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments."),
1702
1
            strSubVersion.size(), MAX_SUBVERSION_LENGTH));
1703
1
    }
1704
1705
    // Requesting DNS seeds entails connecting to IPv4/IPv6, which -onlynet options may prohibit:
1706
    // If -dnsseed=1 is explicitly specified, abort. If it's left unspecified by the user, we skip
1707
    // the DNS seeds by adjusting -dnsseed in InitParameterInteraction.
1708
1.06k
    if (args.GetBoolArg("-dnsseed") == true && !g_reachable_nets.Contains(NET_IPV4) && !g_reachable_nets.Contains(NET_IPV6)) {
1709
1
        return InitError(strprintf(_("Incompatible options: -dnsseed=1 was explicitly specified, but -onlynet forbids connections to IPv4/IPv6")));
1710
1.05k
    };
1711
1712
    // Check for host lookup allowed before parsing any network related parameters
1713
1.05k
    fNameLookup = args.GetBoolArg("-dns", DEFAULT_NAME_LOOKUP);
1714
1715
1.05k
    bool proxyRandomize = args.GetBoolArg("-proxyrandomize", DEFAULT_PROXYRANDOMIZE);
1716
    // -proxy sets a proxy for outgoing network traffic, possibly per network.
1717
    // -noproxy, -proxy=0 or -proxy="" can be used to remove the proxy setting, this is the default
1718
1.05k
    Proxy ipv4_proxy;
1719
1.05k
    Proxy ipv6_proxy;
1720
1.05k
    Proxy onion_proxy;
1721
1.05k
    Proxy name_proxy;
1722
1.05k
    Proxy cjdns_proxy;
1723
1.05k
    for (const std::string& param_value : args.GetArgs("-proxy")) {
1724
49
        const auto eq_pos{param_value.rfind('=')};
1725
49
        const std::string proxy_str{param_value.substr(0, eq_pos)}; // e.g. 127.0.0.1:9050=ipv4 -> 127.0.0.1:9050
1726
49
        std::string net_str;
1727
49
        if (eq_pos != std::string::npos) {
1728
7
            if (eq_pos + 1 == param_value.length()) {
1729
1
                return InitError(strprintf(_("Invalid -proxy address or hostname, ends with '=': '%s'"), param_value));
1730
1
            }
1731
6
            net_str = ToLower(param_value.substr(eq_pos + 1)); // e.g. 127.0.0.1:9050=ipv4 -> ipv4
1732
6
        }
1733
1734
48
        Proxy proxy;
1735
48
        if (!proxy_str.empty() && proxy_str != "0") {
1736
47
            if (IsUnixSocketPath(proxy_str)) {
1737
1
                proxy = Proxy{proxy_str, /*tor_stream_isolation=*/proxyRandomize};
1738
46
            } else {
1739
46
                const std::optional<CService> addr{Lookup(proxy_str, DEFAULT_TOR_SOCKS_PORT, fNameLookup)};
1740
46
                if (!addr.has_value()) {
1741
2
                    return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxy_str));
1742
2
                }
1743
44
                proxy = Proxy{addr.value(), /*tor_stream_isolation=*/proxyRandomize};
1744
44
            }
1745
45
            if (!proxy.IsValid()) {
1746
0
                return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxy_str));
1747
0
            }
1748
45
        }
1749
1750
46
        if (net_str.empty()) { // For all networks.
1751
40
            ipv4_proxy = ipv6_proxy = name_proxy = cjdns_proxy = onion_proxy = proxy;
1752
40
        } else if (net_str == "ipv4") {
1753
1
            ipv4_proxy = name_proxy = proxy;
1754
5
        } else if (net_str == "ipv6") {
1755
2
            ipv6_proxy = name_proxy = proxy;
1756
3
        } else if (net_str == "onion") {
1757
1
            onion_proxy = proxy;
1758
2
        } else if (net_str == "cjdns") {
1759
1
            cjdns_proxy = proxy;
1760
1
        } else {
1761
1
            return InitError(strprintf(_("Unrecognized network in -proxy='%s': '%s'"), param_value, net_str));
1762
1
        }
1763
46
    }
1764
1.05k
    if (ipv4_proxy.IsValid()) {
1765
41
        SetProxy(NET_IPV4, ipv4_proxy);
1766
41
    }
1767
1.05k
    if (ipv6_proxy.IsValid()) {
1768
42
        SetProxy(NET_IPV6, ipv6_proxy);
1769
42
    }
1770
1.05k
    if (name_proxy.IsValid()) {
1771
42
        SetNameProxy(name_proxy);
1772
42
    }
1773
1.05k
    if (cjdns_proxy.IsValid()) {
1774
39
        SetProxy(NET_CJDNS, cjdns_proxy);
1775
39
    }
1776
1777
1.05k
    const bool onlynet_used_with_onion{!onlynets.empty() && g_reachable_nets.Contains(NET_ONION)};
1778
1779
    // -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
1780
    // -noonion (or -onion=0) disables connecting to .onion entirely
1781
    // An empty string is used to not override the onion proxy (in which case it defaults to -proxy set above, or none)
1782
1.05k
    std::string onionArg = args.GetArg("-onion", "");
1783
1.05k
    if (onionArg != "") {
1784
12
        if (onionArg == "0") { // Handle -noonion/-onion=0
1785
3
            onion_proxy = Proxy{};
1786
3
            if (onlynet_used_with_onion) {
1787
2
                return InitError(
1788
2
                    _("Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "
1789
2
                      "reaching the Tor network is explicitly forbidden: -onion=0"));
1790
2
            }
1791
9
        } else {
1792
9
            if (IsUnixSocketPath(onionArg)) {
1793
1
                onion_proxy = Proxy(onionArg, /*tor_stream_isolation=*/proxyRandomize);
1794
8
            } else {
1795
8
                const std::optional<CService> addr{Lookup(onionArg, DEFAULT_TOR_SOCKS_PORT, fNameLookup)};
1796
8
                if (!addr.has_value() || !addr->IsValid()) {
1797
1
                    return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg));
1798
1
                }
1799
1800
7
                onion_proxy = Proxy(addr.value(), /*tor_stream_isolation=*/proxyRandomize);
1801
7
            }
1802
9
        }
1803
12
    }
1804
1805
1.05k
    const bool listenonion{args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)};
1806
1.05k
    if (onion_proxy.IsValid()) {
1807
44
        SetProxy(NET_ONION, onion_proxy);
1808
1.00k
    } else {
1809
        // If -listenonion is set, then we will (try to) connect to the Tor control port
1810
        // later from the torcontrol thread and may retrieve the onion proxy from there.
1811
1.00k
        if (onlynet_used_with_onion && !listenonion) {
1812
1
            return InitError(
1813
1
                _("Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "
1814
1
                  "reaching the Tor network is not provided: none of -proxy, -onion or "
1815
1
                  "-listenonion is given"));
1816
1
        }
1817
1.00k
        g_reachable_nets.Remove(NET_ONION);
1818
1.00k
    }
1819
1820
1.05k
    for (const std::string& strAddr : args.GetArgs("-externalip")) {
1821
12
        const std::optional<CService> addrLocal{Lookup(strAddr, GetListenPort(), fNameLookup)};
1822
12
        if (addrLocal.has_value() && addrLocal->IsValid())
1823
12
            AddLocal(addrLocal.value(), LOCAL_MANUAL);
1824
0
        else
1825
0
            return InitError(ResolveErrMsg("externalip", strAddr));
1826
12
    }
1827
1828
#ifdef ENABLE_ZMQ
1829
    g_zmq_notification_interface = CZMQNotificationInterface::Create(
1830
        [&chainman = node.chainman](std::vector<std::byte>& block, const CBlockIndex& index) {
1831
            assert(chainman);
1832
            if (auto ret{chainman->m_blockman.ReadRawBlock(WITH_LOCK(cs_main, return index.GetBlockPos()))}) {
1833
                block = std::move(*ret);
1834
                return true;
1835
            }
1836
            return false;
1837
        });
1838
1839
    if (g_zmq_notification_interface) {
1840
        validation_signals.RegisterValidationInterface(g_zmq_notification_interface.get());
1841
    }
1842
#endif
1843
1844
    // ********************************************************* Step 7: load block chain
1845
1846
    // cache size calculations
1847
1.05k
    node::LogOversizedDbCache(args);
1848
1.05k
    const auto [index_cache_sizes, kernel_cache_sizes] = CalculateCacheSizes(args, g_enabled_filter_types.size());
1849
1850
1.05k
    LogInfo("Cache configuration:");
1851
1.05k
    LogInfo("* Using %.1f MiB for block index database", kernel_cache_sizes.block_tree_db / double(1_MiB));
1852
1.05k
    if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
1853
45
        LogInfo("* Using %.1f MiB for transaction index database", index_cache_sizes.tx_index / double(1_MiB));
1854
45
    }
1855
1.05k
    if (args.GetBoolArg("-txospenderindex", DEFAULT_TXOSPENDERINDEX)) {
1856
33
        LogInfo("* Using %.1f MiB for transaction output spender index database", index_cache_sizes.txospender_index / double(1_MiB));
1857
33
    }
1858
1.05k
    for (BlockFilterType filter_type : g_enabled_filter_types) {
1859
49
        LogInfo("* Using %.1f MiB for %s block filter index database",
1860
49
                  index_cache_sizes.filter_index / double(1_MiB), BlockFilterTypeName(filter_type));
1861
49
    }
1862
1.05k
    LogInfo("* Using %.1f MiB for chain state database", kernel_cache_sizes.coins_db / double(1_MiB));
1863
1864
1.05k
    assert(!node.mempool);
1865
1.05k
    assert(!node.chainman);
1866
1867
1.05k
    bool do_reindex{args.GetBoolArg("-reindex", false)};
1868
1.05k
    const bool do_reindex_chainstate{args.GetBoolArg("-reindex-chainstate", false)};
1869
1870
    // Chainstate initialization and loading may be retried once with reindexing by GUI users
1871
1.05k
    auto [status, error] = InitAndLoadChainstate(
1872
1.05k
        node,
1873
1.05k
        do_reindex,
1874
1.05k
        do_reindex_chainstate,
1875
1.05k
        kernel_cache_sizes,
1876
1.05k
        args);
1877
1.05k
    if (status == ChainstateLoadStatus::FAILURE && !do_reindex && !ShutdownRequested(node)) {
1878
        // suggest a reindex
1879
12
        bool do_retry{HasTestOption(args, "reindex_after_failure_noninteractive_yes") ||
1880
12
            uiInterface.ThreadSafeQuestion(
1881
11
            error + Untranslated(".\n\n") + _("Do you want to rebuild the databases now?"),
1882
11
            error.original + ".\nPlease restart with -reindex or -reindex-chainstate to recover.",
1883
11
            CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT)};
1884
12
        if (!do_retry) {
1885
11
            return false;
1886
11
        }
1887
1
        do_reindex = true;
1888
1
        if (!Assert(node.shutdown_signal)->reset()) {
1889
0
            LogError("Internal error: failed to reset shutdown signal.\n");
1890
0
        }
1891
1
        std::tie(status, error) = InitAndLoadChainstate(
1892
1
            node,
1893
1
            do_reindex,
1894
1
            do_reindex_chainstate,
1895
1
            kernel_cache_sizes,
1896
1
            args);
1897
1
    }
1898
1.04k
    if (status != ChainstateLoadStatus::SUCCESS && status != ChainstateLoadStatus::INTERRUPTED) {
1899
3
        return InitError(error);
1900
3
    }
1901
1902
    // As LoadBlockIndex can take several minutes, it's possible the user
1903
    // requested to kill the GUI during the last operation. If so, exit.
1904
1.03k
    if (ShutdownRequested(node)) {
1905
11
        LogInfo("Shutdown requested. Exiting.");
1906
11
        return true;
1907
11
    }
1908
1909
1.02k
    ChainstateManager& chainman = *Assert(node.chainman);
1910
1.02k
    auto& kernel_notifications{*Assert(node.notifications)};
1911
1912
1.02k
    assert(!node.peerman);
1913
1.02k
    node.peerman = PeerManager::make(*node.connman, *node.addrman,
1914
1.02k
                                     node.banman.get(), chainman,
1915
1.02k
                                     *node.mempool, *node.warnings,
1916
1.02k
                                     peerman_opts);
1917
1.02k
    validation_signals.RegisterValidationInterface(node.peerman.get());
1918
1919
    // ********************************************************* Step 8: start indexers
1920
1921
1.02k
    if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
1922
35
        g_txindex = std::make_unique<TxIndex>(interfaces::MakeChain(node), index_cache_sizes.tx_index, false, do_reindex);
1923
35
        node.indexes.emplace_back(g_txindex.get());
1924
35
    }
1925
1926
1.02k
    if (args.GetBoolArg("-txospenderindex", DEFAULT_TXOSPENDERINDEX)) {
1927
23
        g_txospenderindex = std::make_unique<TxoSpenderIndex>(interfaces::MakeChain(node), index_cache_sizes.txospender_index, false, do_reindex);
1928
23
        node.indexes.emplace_back(g_txospenderindex.get());
1929
23
    }
1930
1931
1.02k
    for (const auto& filter_type : g_enabled_filter_types) {
1932
39
        InitBlockFilterIndex([&]{ return interfaces::MakeChain(node); }, filter_type, index_cache_sizes.filter_index, false, do_reindex);
1933
39
        node.indexes.emplace_back(GetBlockFilterIndex(filter_type));
1934
39
    }
1935
1936
1.02k
    if (args.GetBoolArg("-coinstatsindex", DEFAULT_COINSTATSINDEX)) {
1937
40
        g_coin_stats_index = std::make_unique<CoinStatsIndex>(interfaces::MakeChain(node), /*cache_size=*/0, false, do_reindex);
1938
40
        node.indexes.emplace_back(g_coin_stats_index.get());
1939
40
    }
1940
1941
    // Init indexes
1942
1.02k
    for (auto index : node.indexes) if (!index->Init()) return false;
1943
1944
    // ********************************************************* Step 9: load wallet
1945
1.02k
    for (const auto& client : node.chain_clients) {
1946
347
        if (!client->load()) {
1947
0
            return false;
1948
0
        }
1949
347
    }
1950
1951
    // ********************************************************* Step 10: data directory maintenance
1952
1953
    // if pruning, perform the initial blockstore prune
1954
    // after any wallet rescanning has taken place.
1955
1.02k
    if (chainman.m_blockman.IsPruneMode()) {
1956
39
        if (chainman.m_blockman.m_blockfiles_indexed) {
1957
37
            LOCK(cs_main);
1958
37
            for (const auto& chainstate : chainman.m_chainstates) {
1959
37
                uiInterface.InitMessage(_("Pruning blockstore…"));
1960
37
                chainstate->PruneAndFlush();
1961
37
            }
1962
37
        }
1963
987
    } else {
1964
        // Prior to setting NODE_NETWORK, check if we can provide historical blocks.
1965
987
        if (!WITH_LOCK(chainman.GetMutex(), return chainman.HistoricalChainstate())) {
1966
979
            LogInfo("Setting NODE_NETWORK in non-prune mode");
1967
979
            g_local_services = ServiceFlags(g_local_services | NODE_NETWORK);
1968
979
        } else {
1969
8
            LogInfo("Running node in NODE_NETWORK_LIMITED mode until snapshot background sync completes");
1970
8
        }
1971
987
    }
1972
1973
    // ********************************************************* Step 11: import blocks
1974
1975
1.02k
    if (!CheckDiskSpace(args.GetDataDirNet())) {
1976
0
        InitError(strprintf(_("Error: Disk space is low for %s"), fs::quoted(fs::PathToString(args.GetDataDirNet()))));
1977
0
        return false;
1978
0
    }
1979
1.02k
    if (!CheckDiskSpace(args.GetBlocksDirPath())) {
1980
0
        InitError(strprintf(_("Error: Disk space is low for %s"), fs::quoted(fs::PathToString(args.GetBlocksDirPath()))));
1981
0
        return false;
1982
0
    }
1983
1984
1.02k
    int chain_active_height = WITH_LOCK(cs_main, return chainman.ActiveChain().Height());
1985
1986
    // On first startup, warn on low block storage space
1987
1.02k
    if (!do_reindex && !do_reindex_chainstate && chain_active_height <= 1) {
1988
424
        uint64_t assumed_chain_bytes{chainparams.AssumedBlockchainSize() * 1_GiB};
1989
424
        uint64_t additional_bytes_needed{
1990
424
            chainman.m_blockman.IsPruneMode() ?
1991
21
                std::min(chainman.m_blockman.GetPruneTarget(), assumed_chain_bytes) :
1992
424
                assumed_chain_bytes};
1993
1994
424
        if (!CheckDiskSpace(args.GetBlocksDirPath(), additional_bytes_needed)) {
1995
1
            InitWarning(strprintf(_(
1996
1
                    "Disk space for %s may not accommodate the block files. " \
1997
1
                    "Approximately %u GB of data will be stored in this directory."
1998
1
                ),
1999
1
                fs::quoted(fs::PathToString(args.GetBlocksDirPath())),
2000
1
                chainparams.AssumedBlockchainSize()
2001
1
            ));
2002
1
        }
2003
424
    }
2004
2005
#ifdef __APPLE__
2006
    auto check_and_warn_fs{[&](const fs::path& path, std::string_view desc) {
2007
        const auto path_desc{strprintf("%s (\"%s\")", desc, fs::PathToString(path))};
2008
        switch (GetFilesystemType(path)) {
2009
        case FSType::EXFAT:
2010
            InitWarning(strprintf(_("The %s path uses exFAT, which is known to have intermittent corruption problems on macOS. "
2011
                "Move this directory to a different filesystem to avoid data loss."), path_desc));
2012
            break;
2013
        case FSType::ERROR:
2014
            LogInfo("Failed to detect filesystem type for %s", path_desc);
2015
            break;
2016
        case FSType::OTHER:
2017
            break;
2018
        }
2019
    }};
2020
2021
    check_and_warn_fs(args.GetDataDirNet(), "data directory");
2022
    check_and_warn_fs(args.GetBlocksDirPath(), "blocks directory");
2023
#endif
2024
2025
1.02k
#if HAVE_SYSTEM
2026
1.02k
    const std::string block_notify = args.GetArg("-blocknotify", "");
2027
1.02k
    if (!block_notify.empty()) {
2028
113
        uiInterface.NotifyBlockTip.connect([block_notify](SynchronizationState sync_state, const CBlockIndex& block, double /* verification_progress */) {
2029
113
            if (sync_state != SynchronizationState::POST_INIT) return;
2030
112
            std::string command = block_notify;
2031
112
            ReplaceAll(command, "%s", block.GetBlockHash().GetHex());
2032
112
            std::thread t(runCommand, command);
2033
112
            t.detach(); // thread runs free
2034
112
        });
2035
1
    }
2036
1.02k
#endif
2037
2038
1.02k
    std::vector<fs::path> vImportFiles;
2039
1.02k
    for (const std::string& strFile : args.GetArgs("-loadblock")) {
2040
1
        vImportFiles.push_back(fs::PathFromString(strFile));
2041
1
    }
2042
2043
    /// \anchor initload
2044
1.02k
    node.background_init_thread = std::thread(&util::TraceThread, "initload", [=, &chainman, &args, &node] {
2045
1.01k
        ScheduleBatchPriority();
2046
        // Import blocks and ActivateBestChain()
2047
1.01k
        ImportBlocks(chainman, vImportFiles);
2048
1.01k
        WITH_LOCK(::cs_main, chainman.UpdateIBDStatus());
2049
1.01k
        if (args.GetBoolArg("-stopafterblockimport", DEFAULT_STOPAFTERBLOCKIMPORT)) {
2050
0
            LogInfo("Stopping after block import");
2051
0
            if (!(Assert(node.shutdown_request))()) {
2052
0
                LogError("Failed to send shutdown signal after finishing block import\n");
2053
0
            }
2054
0
            return;
2055
0
        }
2056
2057
        // Start indexes initial sync
2058
1.01k
        if (!StartIndexBackgroundSync(node)) {
2059
0
            bilingual_str err_str = _("Failed to start indexes, shutting down…");
2060
0
            chainman.GetNotifications().fatalError(err_str);
2061
0
            return;
2062
0
        }
2063
        // Load mempool from disk
2064
1.01k
        if (auto* pool{chainman.ActiveChainstate().GetMempool()}) {
2065
1.01k
            LoadMempool(*pool, ShouldPersistMempool(args) ? MempoolPath(args) : fs::path{}, chainman.ActiveChainstate(), {});
2066
1.01k
            pool->SetLoadTried(!chainman.m_interrupt);
2067
1.01k
        }
2068
1.01k
    });
2069
2070
    /*
2071
     * Wait for genesis block to be processed. Typically kernel_notifications.m_tip_block
2072
     * has already been set by a call to LoadChainTip() in CompleteChainstateInitialization().
2073
     * But this is skipped if the chainstate doesn't exist yet or is being wiped:
2074
     *
2075
     * 1. first startup with an empty datadir
2076
     * 2. reindex
2077
     * 3. reindex-chainstate
2078
     *
2079
     * In these case it's connected by a call to ActivateBestChain() in the initload thread.
2080
     */
2081
1.02k
    {
2082
1.02k
        WAIT_LOCK(kernel_notifications.m_tip_block_mutex, lock);
2083
1.33k
        kernel_notifications.m_tip_block_cv.wait(lock, [&]() EXCLUSIVE_LOCKS_REQUIRED(kernel_notifications.m_tip_block_mutex) {
2084
1.33k
            return kernel_notifications.TipBlock() || ShutdownRequested(node);
2085
1.33k
        });
2086
1.02k
    }
2087
2088
1.02k
    if (ShutdownRequested(node)) {
2089
0
        return true;
2090
0
    }
2091
2092
    // ********************************************************* Step 12: start node
2093
2094
1.02k
    int64_t best_block_time{};
2095
1.02k
    {
2096
1.02k
        LOCK(chainman.GetMutex());
2097
1.02k
        const auto& tip{*Assert(chainman.ActiveTip())};
2098
1.02k
        LogInfo("block tree size = %u", chainman.BlockIndex().size());
2099
1.02k
        chain_active_height = tip.nHeight;
2100
1.02k
        best_block_time = tip.GetBlockTime();
2101
1.02k
        if (tip_info) {
2102
0
            tip_info->block_height = chain_active_height;
2103
0
            tip_info->block_time = best_block_time;
2104
0
            tip_info->verification_progress = chainman.GuessVerificationProgress(&tip);
2105
0
        }
2106
1.02k
        if (tip_info && chainman.m_best_header) {
2107
0
            tip_info->header_height = chainman.m_best_header->nHeight;
2108
0
            tip_info->header_time = chainman.m_best_header->GetBlockTime();
2109
0
        }
2110
1.02k
    }
2111
1.02k
    LogInfo("nBestHeight = %d", chain_active_height);
2112
1.02k
    if (node.peerman) node.peerman->SetBestBlock(chain_active_height, std::chrono::seconds{best_block_time});
2113
2114
    // Map ports with NAT-PMP
2115
1.02k
    StartMapPort(args.GetBoolArg("-natpmp", DEFAULT_NATPMP));
2116
2117
1.02k
    CConnman::Options connOptions;
2118
1.02k
    connOptions.m_local_services = g_local_services;
2119
1.02k
    connOptions.m_max_automatic_connections = nMaxConnections;
2120
1.02k
    connOptions.uiInterface = &uiInterface;
2121
1.02k
    connOptions.m_banman = node.banman.get();
2122
1.02k
    connOptions.m_msgproc = node.peerman.get();
2123
1.02k
    connOptions.nSendBufferMaxSize = 1000 * args.GetIntArg("-maxsendbuffer", DEFAULT_MAXSENDBUFFER);
2124
1.02k
    connOptions.nReceiveFloodSize = 1000 * args.GetIntArg("-maxreceivebuffer", DEFAULT_MAXRECEIVEBUFFER);
2125
1.02k
    connOptions.m_added_nodes = args.GetArgs("-addnode");
2126
1.02k
    connOptions.nMaxOutboundLimit = *opt_max_upload;
2127
1.02k
    connOptions.m_peer_connect_timeout = peer_connect_timeout;
2128
1.02k
    connOptions.whitelist_forcerelay = args.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY);
2129
1.02k
    connOptions.whitelist_relay = args.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY);
2130
1.02k
    connOptions.m_capture_messages = args.GetBoolArg("-capturemessages", false);
2131
2132
    // Port to bind to if `-bind=addr` is provided without a `:port` suffix.
2133
1.02k
    const uint16_t default_bind_port =
2134
1.02k
        static_cast<uint16_t>(args.GetIntArg("-port", Params().GetDefaultPort()));
2135
2136
1.02k
    const uint16_t default_bind_port_onion = default_bind_port + 1;
2137
2138
1.02k
    const auto BadPortWarning = [](const char* prefix, uint16_t port) {
2139
0
        return strprintf(_("%s request to listen on port %u. This port is considered \"bad\" and "
2140
0
                           "thus it is unlikely that any peer will connect to it. See "
2141
0
                           "doc/p2p-bad-ports.md for details and a full list."),
2142
0
                         prefix,
2143
0
                         port);
2144
0
    };
2145
2146
1.02k
    for (const std::string& bind_arg : args.GetArgs("-bind")) {
2147
1.01k
        std::optional<CService> bind_addr;
2148
1.01k
        const size_t index = bind_arg.rfind('=');
2149
1.01k
        if (index == std::string::npos) {
2150
991
            bind_addr = Lookup(bind_arg, default_bind_port, /*fAllowLookup=*/false);
2151
991
            if (bind_addr.has_value()) {
2152
991
                connOptions.vBinds.push_back(bind_addr.value());
2153
991
                if (IsBadPort(bind_addr.value().GetPort())) {
2154
0
                    InitWarning(BadPortWarning("-bind", bind_addr.value().GetPort()));
2155
0
                }
2156
991
                continue;
2157
991
            }
2158
991
        } else {
2159
22
            const std::string network_type = bind_arg.substr(index + 1);
2160
22
            if (network_type == "onion") {
2161
22
                const std::string truncated_bind_arg = bind_arg.substr(0, index);
2162
22
                bind_addr = Lookup(truncated_bind_arg, default_bind_port_onion, false);
2163
22
                if (bind_addr.has_value()) {
2164
22
                    connOptions.onion_binds.push_back(bind_addr.value());
2165
22
                    continue;
2166
22
                }
2167
22
            }
2168
22
        }
2169
0
        return InitError(ResolveErrMsg("bind", bind_arg));
2170
1.01k
    }
2171
2172
1.02k
    for (const std::string& strBind : args.GetArgs("-whitebind")) {
2173
9
        NetWhitebindPermissions whitebind;
2174
9
        bilingual_str error;
2175
9
        if (!NetWhitebindPermissions::TryParse(strBind, whitebind, error)) return InitError(error);
2176
8
        connOptions.vWhiteBinds.push_back(whitebind);
2177
8
    }
2178
2179
    // If the user did not specify -bind= or -whitebind= then we bind
2180
    // on any address - 0.0.0.0 (IPv4) and :: (IPv6).
2181
1.02k
    connOptions.bind_on_any = args.GetArgs("-bind").empty() && args.GetArgs("-whitebind").empty();
2182
2183
    // Emit a warning if a bad port is given to -port= but only if -bind and -whitebind are not
2184
    // given, because if they are, then -port= is ignored.
2185
1.02k
    if (connOptions.bind_on_any && args.IsArgSet("-port")) {
2186
21
        const uint16_t port_arg = args.GetIntArg("-port", 0);
2187
21
        if (IsBadPort(port_arg)) {
2188
0
            InitWarning(BadPortWarning("-port", port_arg));
2189
0
        }
2190
21
    }
2191
2192
1.02k
    CService onion_service_target;
2193
1.02k
    if (!connOptions.onion_binds.empty()) {
2194
20
        onion_service_target = connOptions.onion_binds.front();
2195
1.00k
    } else if (!connOptions.vBinds.empty()) {
2196
975
        onion_service_target = connOptions.vBinds.front();
2197
975
    } else {
2198
30
        onion_service_target = DefaultOnionServiceTarget(default_bind_port_onion);
2199
30
        connOptions.onion_binds.push_back(onion_service_target);
2200
30
    }
2201
2202
1.02k
    if (listenonion) {
2203
8
        if (connOptions.onion_binds.size() > 1) {
2204
0
            InitWarning(strprintf(_("More than one onion bind address is provided. Using %s "
2205
0
                                    "for the automatically created Tor onion service."),
2206
0
                                  onion_service_target.ToStringAddrPort()));
2207
0
        }
2208
8
        node.tor_controller = std::make_unique<TorController>(gArgs.GetArg("-torcontrol", DEFAULT_TOR_CONTROL), onion_service_target);
2209
8
    }
2210
2211
1.02k
    bool should_discover = connOptions.bind_on_any;
2212
1.02k
    if (!should_discover) {
2213
996
        for (const auto& bind : connOptions.vBinds) {
2214
990
            if (bind.IsBindAny()) {
2215
13
                should_discover = true;
2216
13
                break;
2217
13
            }
2218
990
        }
2219
996
    }
2220
2221
1.02k
    if (!should_discover) {
2222
983
        for (const auto& whitebind : connOptions.vWhiteBinds) {
2223
6
            if (whitebind.m_service.IsBindAny()) {
2224
1
                should_discover = true;
2225
1
                break;
2226
1
            }
2227
6
        }
2228
983
    }
2229
2230
1.02k
    if (should_discover) {
2231
        // Only add all IP addresses of the machine if we would be listening on
2232
        // any address - 0.0.0.0 (IPv4) and :: (IPv6).
2233
36
        Discover();
2234
36
    }
2235
2236
1.02k
    for (const auto& net : args.GetArgs("-whitelist")) {
2237
146
        NetWhitelistPermissions subnet;
2238
146
        ConnectionDirection connection_direction;
2239
146
        bilingual_str error;
2240
146
        if (!NetWhitelistPermissions::TryParse(net, subnet, connection_direction, error)) return InitError(error);
2241
143
        if (connection_direction & ConnectionDirection::In) {
2242
142
            connOptions.vWhitelistedRangeIncoming.push_back(subnet);
2243
142
        }
2244
143
        if (connection_direction & ConnectionDirection::Out) {
2245
110
            connOptions.vWhitelistedRangeOutgoing.push_back(subnet);
2246
110
        }
2247
143
    }
2248
2249
1.02k
    connOptions.vSeedNodes = args.GetArgs("-seednode");
2250
2251
1.02k
    const auto connect = args.GetArgs("-connect");
2252
1.02k
    if (!connect.empty() || args.IsArgNegated("-connect")) {
2253
        // Do not initiate other outgoing connections when connecting to trusted
2254
        // nodes, or when -noconnect is specified.
2255
981
        connOptions.m_use_addrman_outgoing = false;
2256
2257
981
        if (connect.size() != 1 || connect[0] != "0") {
2258
9
            connOptions.m_specified_outgoing = connect;
2259
9
        }
2260
981
        if (!connOptions.m_specified_outgoing.empty() && !connOptions.vSeedNodes.empty()) {
2261
1
            LogInfo("-seednode is ignored when -connect is used");
2262
1
        }
2263
2264
981
        if (args.IsArgSet("-dnsseed") && args.GetBoolArg("-dnsseed", DEFAULT_DNSSEED) && args.IsArgSet("-proxy")) {
2265
12
            LogInfo("-dnsseed is ignored when -connect is used and -proxy is specified");
2266
12
        }
2267
981
    }
2268
2269
1.02k
    const std::string& i2psam_arg = args.GetArg("-i2psam", "");
2270
1.02k
    if (!i2psam_arg.empty()) {
2271
7
        const std::optional<CService> addr{Lookup(i2psam_arg, 7656, fNameLookup)};
2272
7
        if (!addr.has_value() || !addr->IsValid()) {
2273
1
            return InitError(strprintf(_("Invalid -i2psam address or hostname: '%s'"), i2psam_arg));
2274
1
        }
2275
6
        SetProxy(NET_I2P, Proxy{addr.value()});
2276
1.01k
    } else {
2277
1.01k
        if (!onlynets.empty() && g_reachable_nets.Contains(NET_I2P)) {
2278
1
            return InitError(
2279
1
                _("Outbound connections restricted to i2p (-onlynet=i2p) but "
2280
1
                  "-i2psam is not provided"));
2281
1
        }
2282
1.01k
        g_reachable_nets.Remove(NET_I2P);
2283
1.01k
    }
2284
2285
1.02k
    connOptions.m_i2p_accept_incoming = args.GetBoolArg("-i2pacceptincoming", DEFAULT_I2P_ACCEPT_INCOMING);
2286
2287
1.02k
    if (auto conflict = CheckBindingConflicts(connOptions)) {
2288
6
        return InitError(strprintf(
2289
6
            _("Duplicate binding configuration for address %s. "
2290
6
                "Please check your -bind, -bind=...=onion and -whitebind settings."),
2291
6
                    conflict->ToStringAddrPort()));
2292
6
    }
2293
2294
1.01k
    if (args.GetBoolArg("-privatebroadcast", DEFAULT_PRIVATE_BROADCAST)) {
2295
        // If -listenonion is set, then NET_ONION may not be reachable now
2296
        // but may become reachable later, thus only error here if it is not
2297
        // reachable and will not become reachable for sure.
2298
7
        const bool onion_may_become_reachable{listenonion && (!args.IsArgSet("-onlynet") || onlynet_used_with_onion)};
2299
7
        if (!g_reachable_nets.Contains(NET_I2P) &&
2300
7
            !g_reachable_nets.Contains(NET_ONION) &&
2301
7
            !onion_may_become_reachable) {
2302
1
            return InitError(_("Private broadcast of own transactions requested (-privatebroadcast), "
2303
1
                               "but none of Tor or I2P networks is reachable"));
2304
1
        }
2305
6
        if (!connOptions.m_use_addrman_outgoing) {
2306
1
            return InitError(_("Private broadcast of own transactions requested (-privatebroadcast), "
2307
1
                               "but -connect is also configured. They are incompatible because the "
2308
1
                               "private broadcast needs to open new connections to randomly "
2309
1
                               "chosen Tor or I2P peers. Consider using -maxconnections=0 -addnode=... "
2310
1
                               "instead"));
2311
1
        }
2312
5
        if (!proxyRandomize && (g_reachable_nets.Contains(NET_ONION) || onion_may_become_reachable)) {
2313
1
            InitWarning(_("Private broadcast of own transactions requested (-privatebroadcast) and "
2314
1
                          "-proxyrandomize is disabled. Tor circuits for private broadcast connections "
2315
1
                          "may be correlated to other connections over Tor. For maximum privacy set "
2316
1
                          "-proxyrandomize=1."));
2317
1
        }
2318
5
    }
2319
2320
1.01k
    if (!node.connman->Start(scheduler, connOptions)) {
2321
11
        return false;
2322
11
    }
2323
2324
    // ********************************************************* Step 13: finished
2325
2326
    // At this point, the RPC is "started", but still in warmup, which means it
2327
    // cannot yet be called. Before we make it callable, we need to make sure
2328
    // that the RPC's view of the best block is valid and consistent with
2329
    // ChainstateManager's active tip.
2330
1.00k
    SetRPCWarmupFinished();
2331
2332
1.00k
    uiInterface.InitMessage(_("Done loading"));
2333
2334
1.00k
    for (const auto& client : node.chain_clients) {
2335
345
        client->start(scheduler);
2336
345
    }
2337
2338
1.00k
    BanMan* banman = node.banman.get();
2339
1.00k
    scheduler.scheduleEvery([banman]{
2340
9
        banman->DumpBanlist();
2341
9
    }, DUMP_BANS_INTERVAL);
2342
2343
1.00k
    if (node.peerman) node.peerman->StartScheduledTasks(scheduler);
2344
2345
1.00k
#if HAVE_SYSTEM
2346
1.00k
    StartupNotify(args);
2347
1.00k
#endif
2348
2349
1.00k
    return true;
2350
1.01k
}
2351
2352
bool StartIndexBackgroundSync(NodeContext& node)
2353
1.01k
{
2354
1.01k
    ChainstateManager& chainman = *Assert(node.chainman);
2355
1.01k
    const Chainstate& chainstate = WITH_LOCK(::cs_main, return chainman.ValidatedChainstate());
2356
1.01k
    const CChain& index_chain = chainstate.m_chain;
2357
1.01k
    const int current_height = WITH_LOCK(::cs_main, return index_chain.Height());
2358
2359
    // Skip checking data availability if we have not synced any blocks yet
2360
1.01k
    if (current_height > 0) {
2361
        // Before starting index sync, verify that all required block data is available
2362
        // on disk from each index's current sync position up to the chain tip.
2363
        //
2364
        // This is done separately for undo and block data: First we verify block + undo
2365
        // data existence from tip down to the lowest height required by any index that
2366
        // needs undo data (e.g., coinstatsindex, blockfilterindex). Then, if any
2367
        // block-only index needs to sync from a lower height than previously covered,
2368
        // verify block data existence down to that lower height.
2369
        //
2370
        // This avoids checking undo data for blocks where no index requires it,
2371
        // though currently block and undo data availability are synchronized on disk
2372
        // under normal circumstances.
2373
603
        std::optional<const CBlockIndex*> block_start;
2374
603
        std::string block_start_name;
2375
603
        std::optional<const CBlockIndex*> undo_start;
2376
603
        std::string undo_start_name;
2377
2378
603
        for (const auto& index : node.indexes) {
2379
116
            const IndexSummary& summary = index->GetSummary();
2380
116
            if (summary.synced) continue;
2381
2382
            // Get the last common block between the index best block and the active chain
2383
67
            const CBlockIndex* pindex = nullptr;
2384
67
            {
2385
67
                LOCK(::cs_main);
2386
67
                pindex = chainman.m_blockman.LookupBlockIndex(summary.best_block_hash);
2387
67
                if (!pindex) {
2388
0
                    LogWarning("Failed to find block manager entry for best block %s from %s, falling back to genesis for index sync",
2389
0
                        summary.best_block_hash.ToString(), summary.name);
2390
67
                } else if (!index_chain.Contains(*pindex)) {
2391
1
                    pindex = index_chain.FindFork(*pindex);
2392
1
                }
2393
67
            }
2394
67
            if (!pindex) {
2395
0
                pindex = index_chain.Genesis();
2396
0
            }
2397
2398
67
            bool need_undo = index->CustomOptions().connect_undo_data;
2399
67
            auto& op_start_index = need_undo ? undo_start : block_start;
2400
67
            auto& name_index = need_undo ? undo_start_name : block_start_name;
2401
2402
67
            if (op_start_index && pindex->nHeight >= op_start_index.value()->nHeight) continue;
2403
52
            op_start_index = pindex;
2404
52
            name_index = summary.name;
2405
52
        }
2406
2407
        // Verify all blocks needed to sync to current tip are present including undo data.
2408
603
        if (undo_start) {
2409
25
            LOCK(::cs_main);
2410
25
            if (!chainman.m_blockman.CheckBlockDataAvailability(*index_chain.Tip(), *Assert(undo_start.value()), BlockStatus{BLOCK_HAVE_DATA | BLOCK_HAVE_UNDO})) {
2411
0
                return InitError(Untranslated(strprintf("%s best block of the index goes beyond pruned data (including undo data). Please disable the index or reindex (which will download the whole blockchain again)", undo_start_name)));
2412
0
            }
2413
25
        }
2414
2415
        // Verify all blocks needed to sync to current tip are present unless we already checked all of them above.
2416
603
        if (block_start && !(undo_start && undo_start.value()->nHeight <= block_start.value()->nHeight)) {
2417
5
            LOCK(::cs_main);
2418
5
            if (!chainman.m_blockman.CheckBlockDataAvailability(*index_chain.Tip(), *Assert(block_start.value()), BlockStatus{BLOCK_HAVE_DATA})) {
2419
0
                return InitError(Untranslated(strprintf("%s best block of the index goes beyond pruned data. Please disable the index or reindex (which will download the whole blockchain again)", block_start_name)));
2420
0
            }
2421
5
        }
2422
603
    }
2423
2424
    // Start threads
2425
1.01k
    for (auto index : node.indexes) if (!index->StartBackgroundSync()) return false;
2426
1.01k
    return true;
2427
1.01k
}