Bitcoin Core 28.0.0
P2P Digital Currency
Loading...
Searching...
No Matches
bitcoin.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-2022 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#include <config/bitcoin-config.h> // IWYU pragma: keep
6
7#include <qt/bitcoin.h>
8
9#include <chainparams.h>
10#include <common/args.h>
11#include <common/init.h>
12#include <common/system.h>
13#include <init.h>
14#include <interfaces/handler.h>
15#include <interfaces/init.h>
16#include <interfaces/node.h>
17#include <logging.h>
18#include <node/context.h>
19#include <node/interface_ui.h>
20#include <noui.h>
21#include <qt/bitcoingui.h>
22#include <qt/clientmodel.h>
23#include <qt/guiconstants.h>
24#include <qt/guiutil.h>
25#include <qt/initexecutor.h>
26#include <qt/intro.h>
27#include <qt/networkstyle.h>
28#include <qt/optionsmodel.h>
29#include <qt/platformstyle.h>
30#include <qt/splashscreen.h>
31#include <qt/utilitydialog.h>
33#include <uint256.h>
34#include <util/exception.h>
35#include <util/string.h>
36#include <util/threadnames.h>
37#include <util/translation.h>
38#include <validation.h>
39
40#ifdef ENABLE_WALLET
41#include <qt/paymentserver.h>
42#include <qt/walletcontroller.h>
43#include <qt/walletmodel.h>
44#include <wallet/types.h>
45#endif // ENABLE_WALLET
46
47#include <boost/signals2/connection.hpp>
48#include <chrono>
49#include <memory>
50
51#include <QApplication>
52#include <QDebug>
53#include <QLatin1String>
54#include <QLibraryInfo>
55#include <QLocale>
56#include <QMessageBox>
57#include <QSettings>
58#include <QThread>
59#include <QTimer>
60#include <QTranslator>
61#include <QWindow>
62
63#if defined(QT_STATIC)
64#include <QtPlugin>
65#if defined(QT_QPA_PLATFORM_XCB)
66Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
67#elif defined(QT_QPA_PLATFORM_WINDOWS)
68Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
69Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin);
70#elif defined(QT_QPA_PLATFORM_COCOA)
71Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
72Q_IMPORT_PLUGIN(QMacStylePlugin);
73#elif defined(QT_QPA_PLATFORM_ANDROID)
74Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin)
75#endif
76#endif
77
78// Declare meta types used for QMetaObject::invokeMethod
79Q_DECLARE_METATYPE(bool*)
80Q_DECLARE_METATYPE(CAmount)
81Q_DECLARE_METATYPE(SynchronizationState)
82Q_DECLARE_METATYPE(SyncType)
83Q_DECLARE_METATYPE(uint256)
84#ifdef ENABLE_WALLET
85Q_DECLARE_METATYPE(wallet::AddressPurpose)
86#endif // ENABLE_WALLET
87
89
90static void RegisterMetaTypes()
91{
92 // Register meta types used for QMetaObject::invokeMethod and Qt::QueuedConnection
93 qRegisterMetaType<bool*>();
94 qRegisterMetaType<SynchronizationState>();
95 qRegisterMetaType<SyncType>();
96 #ifdef ENABLE_WALLET
97 qRegisterMetaType<WalletModel*>();
98 qRegisterMetaType<wallet::AddressPurpose>();
99 #endif // ENABLE_WALLET
100 // Register typedefs (see https://doc.qt.io/qt-5/qmetatype.html#qRegisterMetaType)
101 // IMPORTANT: if CAmount is no longer a typedef use the normal variant above (see https://doc.qt.io/qt-5/qmetatype.html#qRegisterMetaType-1)
102 qRegisterMetaType<CAmount>("CAmount");
103 qRegisterMetaType<size_t>("size_t");
104
105 qRegisterMetaType<std::function<void()>>("std::function<void()>");
106 qRegisterMetaType<QMessageBox::Icon>("QMessageBox::Icon");
107 qRegisterMetaType<interfaces::BlockAndHeaderTipInfo>("interfaces::BlockAndHeaderTipInfo");
108
109#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
110 qRegisterMetaTypeStreamOperators<BitcoinUnit>("BitcoinUnit");
111#else
112 qRegisterMetaType<BitcoinUnit>("BitcoinUnit");
113#endif
114}
115
116static QString GetLangTerritory()
117{
118 QSettings settings;
119 // Get desired locale (e.g. "de_DE")
120 // 1) System default language
121 QString lang_territory = QLocale::system().name();
122 // 2) Language from QSettings
123 QString lang_territory_qsettings = settings.value("language", "").toString();
124 if(!lang_territory_qsettings.isEmpty())
125 lang_territory = lang_territory_qsettings;
126 // 3) -lang command line argument
127 lang_territory = QString::fromStdString(gArgs.GetArg("-lang", lang_territory.toStdString()));
128 return lang_territory;
129}
130
132static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTranslator, QTranslator &translatorBase, QTranslator &translator)
133{
134 // Remove old translators
135 QApplication::removeTranslator(&qtTranslatorBase);
136 QApplication::removeTranslator(&qtTranslator);
137 QApplication::removeTranslator(&translatorBase);
138 QApplication::removeTranslator(&translator);
139
140 // Get desired locale (e.g. "de_DE")
141 // 1) System default language
142 QString lang_territory = GetLangTerritory();
143
144 // Convert to "de" only by truncating "_DE"
145 QString lang = lang_territory;
146 lang.truncate(lang_territory.lastIndexOf('_'));
147
148 // Load language files for configured locale:
149 // - First load the translator for the base language, without territory
150 // - Then load the more specific locale translator
151
152#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
153 const QString translation_path{QLibraryInfo::location(QLibraryInfo::TranslationsPath)};
154#else
155 const QString translation_path{QLibraryInfo::path(QLibraryInfo::TranslationsPath)};
156#endif
157 // Load e.g. qt_de.qm
158 if (qtTranslatorBase.load("qt_" + lang, translation_path)) {
159 QApplication::installTranslator(&qtTranslatorBase);
160 }
161
162 // Load e.g. qt_de_DE.qm
163 if (qtTranslator.load("qt_" + lang_territory, translation_path)) {
164 QApplication::installTranslator(&qtTranslator);
165 }
166
167 // Load e.g. bitcoin_de.qm (shortcut "de" needs to be defined in bitcoin.qrc)
168 if (translatorBase.load(lang, ":/translations/")) {
169 QApplication::installTranslator(&translatorBase);
170 }
171
172 // Load e.g. bitcoin_de_DE.qm (shortcut "de_DE" needs to be defined in bitcoin.qrc)
173 if (translator.load(lang_territory, ":/translations/")) {
174 QApplication::installTranslator(&translator);
175 }
176}
177
178static bool ErrorSettingsRead(const bilingual_str& error, const std::vector<std::string>& details)
179{
180 QMessageBox messagebox(QMessageBox::Critical, PACKAGE_NAME, QString::fromStdString(strprintf("%s.", error.translated)), QMessageBox::Reset | QMessageBox::Abort);
181 /*: Explanatory text shown on startup when the settings file cannot be read.
182 Prompts user to make a choice between resetting or aborting. */
183 messagebox.setInformativeText(QObject::tr("Do you want to reset settings to default values, or to abort without making changes?"));
184 messagebox.setDetailedText(QString::fromStdString(MakeUnorderedList(details)));
185 messagebox.setTextFormat(Qt::PlainText);
186 messagebox.setDefaultButton(QMessageBox::Reset);
187 switch (messagebox.exec()) {
188 case QMessageBox::Reset:
189 return false;
190 case QMessageBox::Abort:
191 return true;
192 default:
193 assert(false);
194 }
195}
196
197static void ErrorSettingsWrite(const bilingual_str& error, const std::vector<std::string>& details)
198{
199 QMessageBox messagebox(QMessageBox::Critical, PACKAGE_NAME, QString::fromStdString(strprintf("%s.", error.translated)), QMessageBox::Ok);
200 /*: Explanatory text shown on startup when the settings file could not be written.
201 Prompts user to check that we have the ability to write to the file.
202 Explains that the user has the option of running without a settings file.*/
203 messagebox.setInformativeText(QObject::tr("A fatal error occurred. Check that settings file is writable, or try running with -nosettings."));
204 messagebox.setDetailedText(QString::fromStdString(MakeUnorderedList(details)));
205 messagebox.setTextFormat(Qt::PlainText);
206 messagebox.setDefaultButton(QMessageBox::Ok);
207 messagebox.exec();
208}
209
210/* qDebug() message handler --> debug.log */
211void DebugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString &msg)
212{
213 Q_UNUSED(context);
214 if (type == QtDebugMsg) {
215 LogPrint(BCLog::QT, "GUI: %s\n", msg.toStdString());
216 } else {
217 LogPrintf("GUI: %s\n", msg.toStdString());
218 }
219}
220
221static int qt_argc = 1;
222static const char* qt_argv = "bitcoin-qt";
223
225 : QApplication(qt_argc, const_cast<char**>(&qt_argv))
226{
227 // Qt runs setlocale(LC_ALL, "") on initialization.
229 setQuitOnLastWindowClosed(false);
230}
231
233{
234 // UI per-platform customization
235 // This must be done inside the BitcoinApplication constructor, or after it, because
236 // PlatformStyle::instantiate requires a QApplication
237 std::string platformName;
238 platformName = gArgs.GetArg("-uiplatform", BitcoinGUI::DEFAULT_UIPLATFORM);
239 platformStyle = PlatformStyle::instantiate(QString::fromStdString(platformName));
240 if (!platformStyle) // Fall back to "other" if specified name not found
243}
244
246{
247 m_executor.reset();
248
249 delete window;
250 window = nullptr;
251 delete platformStyle;
252 platformStyle = nullptr;
253}
254
255#ifdef ENABLE_WALLET
256void BitcoinApplication::createPaymentServer()
257{
258 paymentServer = new PaymentServer(this);
259}
260#endif
261
263{
264 optionsModel = new OptionsModel(node(), this);
265 if (resetSettings) {
267 }
268 bilingual_str error;
269 if (!optionsModel->Init(error)) {
270 fs::path settings_path;
271 if (gArgs.GetSettingsPath(&settings_path)) {
272 error += Untranslated("\n");
273 std::string quoted_path = strprintf("%s", fs::quoted(fs::PathToString(settings_path)));
274 error.original += strprintf("Settings file %s might be corrupt or invalid.", quoted_path);
275 error.translated += tr("Settings file %1 might be corrupt or invalid.").arg(QString::fromStdString(quoted_path)).toStdString();
276 }
277 InitError(error);
278 QMessageBox::critical(nullptr, PACKAGE_NAME, QString::fromStdString(error.translated));
279 return false;
280 }
281 return true;
282}
283
285{
286 window = new BitcoinGUI(node(), platformStyle, networkStyle, nullptr);
288
289 pollShutdownTimer = new QTimer(window);
290 connect(pollShutdownTimer, &QTimer::timeout, [this]{
291 if (!QApplication::activeModalWidget()) {
293 }
294 });
295}
296
298{
300 m_splash = new SplashScreen(networkStyle);
301 m_splash->show();
302}
303
310
315
317{
319 m_executor.emplace(node());
320
321 /* communication to and from thread */
323 connect(&m_executor.value(), &InitExecutor::shutdownResult, this, [] {
324 QCoreApplication::exit(0);
325 });
329}
330
332{
333 // Default printtoconsole to false for the GUI. GUI programs should not
334 // print to the console unnecessarily.
335 gArgs.SoftSetBoolArg("-printtoconsole", false);
336
339}
340
342{
344}
345
347{
348 qDebug() << __func__ << ": Requesting initialize";
349 startThread();
350 Q_EMIT requestedInitialize();
351}
352
354{
355 for (const auto w : QGuiApplication::topLevelWindows()) {
356 w->hide();
357 }
358
359 delete m_splash;
360 m_splash = nullptr;
361
362 // Show a simple window indicating shutdown status
363 // Do this first as some of the steps may take some time below,
364 // for example the RPC console may still be executing a command.
366
367 qDebug() << __func__ << ": Requesting shutdown";
368
369 // Must disconnect node signals otherwise current thread can deadlock since
370 // no event loop is running.
372 // Request node shutdown, which can interrupt long operations, like
373 // rescanning a wallet.
375 // Prior to unsetting the client model, stop listening backend signals
376 if (clientModel) {
377 clientModel->stop();
378 }
379
380 // Unsetting the client model can cause the current thread to wait for node
381 // to complete an operation, like wait for a RPC execution to complete.
382 window->setClientModel(nullptr);
383 pollShutdownTimer->stop();
384
385#ifdef ENABLE_WALLET
386 // Delete wallet controller here manually, instead of relying on Qt object
387 // tracking (https://doc.qt.io/qt-5/objecttrees.html). This makes sure
388 // walletmodel m_handle_* notification handlers are deleted before wallets
389 // are unloaded, which can simplify wallet implementations. It also avoids
390 // these notifications having to be handled while GUI objects are being
391 // destroyed, making GUI code less fragile as well.
392 delete m_wallet_controller;
393 m_wallet_controller = nullptr;
394#endif // ENABLE_WALLET
395
396 delete clientModel;
397 clientModel = nullptr;
398
399 // Request shutdown from core thread
400 Q_EMIT requestedShutdown();
401}
402
404{
405 qDebug() << __func__ << ": Initialization result: " << success;
406
407 if (success) {
408 delete m_splash;
409 m_splash = nullptr;
410
411 // Log this only after AppInitMain finishes, as then logging setup is guaranteed complete
412 qInfo() << "Platform customization:" << platformStyle->getName();
414 window->setClientModel(clientModel, &tip_info);
415
416 // If '-min' option passed, start window minimized (iconified) or minimized to tray
417 bool start_minimized = gArgs.GetBoolArg("-min", false);
418#ifdef ENABLE_WALLET
420 m_wallet_controller = new WalletController(*clientModel, platformStyle, this);
421 window->setWalletController(m_wallet_controller, /*show_loading_minimized=*/start_minimized);
422 if (paymentServer) {
423 paymentServer->setOptionsModel(optionsModel);
424 }
425 }
426#endif // ENABLE_WALLET
427
428 // Show or minimize window
429 if (!start_minimized) {
430 window->show();
432 // do nothing as the window is managed by the tray icon
433 } else {
434 window->showMinimized();
435 }
436 Q_EMIT windowShown(window);
437
438#ifdef ENABLE_WALLET
439 // Now that initialization/startup is done, process any command-line
440 // bitcoin: URIs or payment requests:
441 if (paymentServer) {
442 connect(paymentServer, &PaymentServer::receivedPaymentRequest, window, &BitcoinGUI::handlePaymentRequest);
444 connect(paymentServer, &PaymentServer::message, [this](const QString& title, const QString& message, unsigned int style) {
445 window->message(title, message, style);
446 });
447 QTimer::singleShot(100ms, paymentServer, &PaymentServer::uiReady);
448 }
449#endif
451 } else {
453 }
454}
455
457{
458 QMessageBox::critical(
459 nullptr, tr("Runaway exception"),
460 tr("A fatal error occurred. %1 can no longer continue safely and will quit.").arg(PACKAGE_NAME) +
461 QLatin1String("<br><br>") + GUIUtil::MakeHtmlLink(message, PACKAGE_BUGREPORT));
462 ::exit(EXIT_FAILURE);
463}
464
466{
467 assert(QThread::currentThread() == thread());
468 QMessageBox::warning(
469 nullptr, tr("Internal error"),
470 tr("An internal error occurred. %1 will attempt to continue safely. This is "
471 "an unexpected bug which can be reported as described below.").arg(PACKAGE_NAME) +
472 QLatin1String("<br><br>") + GUIUtil::MakeHtmlLink(message, PACKAGE_BUGREPORT));
473}
474
476{
477 if (!window)
478 return 0;
479
480 return window->winId();
481}
482
484{
485 if (e->type() == QEvent::Quit) {
487 return true;
488 }
489
490 return QApplication::event(e);
491}
492
493static void SetupUIArgs(ArgsManager& argsman)
494{
495 argsman.AddArg("-choosedatadir", strprintf("Choose data directory on startup (default: %u)", DEFAULT_CHOOSE_DATADIR), ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
496 argsman.AddArg("-lang=<lang>", "Set language, for example \"de_DE\" (default: system locale)", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
497 argsman.AddArg("-min", "Start minimized", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
498 argsman.AddArg("-resetguisettings", "Reset all settings changed in the GUI", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
499 argsman.AddArg("-splash", strprintf("Show splash screen on startup (default: %u)", DEFAULT_SPLASHSCREEN), ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
500 argsman.AddArg("-uiplatform", strprintf("Select platform to customize UI for (one of windows, macosx, other; default: %s)", BitcoinGUI::DEFAULT_UIPLATFORM), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::GUI);
501}
502
503int GuiMain(int argc, char* argv[])
504{
505#ifdef WIN32
506 common::WinCmdLineArgs winArgs;
507 std::tie(argc, argv) = winArgs.get();
508#endif
509
510 std::unique_ptr<interfaces::Init> init = interfaces::MakeGuiInit(argc, argv);
511
514
515 // Subscribe to global signals from core
516 boost::signals2::scoped_connection handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(noui_ThreadSafeMessageBox);
517 boost::signals2::scoped_connection handler_question = ::uiInterface.ThreadSafeQuestion_connect(noui_ThreadSafeQuestion);
518 boost::signals2::scoped_connection handler_init_message = ::uiInterface.InitMessage_connect(noui_InitMessage);
519
520 // Do not refer to data directory yet, this can be overridden by Intro::pickDataDirectory
521
523 Q_INIT_RESOURCE(bitcoin);
524 Q_INIT_RESOURCE(bitcoin_locale);
525
526#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
527 // Generate high-dpi pixmaps
528 QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
529 QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
530#endif
531
532#if defined(QT_QPA_PLATFORM_ANDROID)
533 QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
534 QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
535 QApplication::setAttribute(Qt::AA_DontUseNativeDialogs);
536#endif
537
539 GUIUtil::LoadFont(QStringLiteral(":/fonts/monospace"));
540
542 // Command-line options take precedence:
545 std::string error;
546 if (!gArgs.ParseParameters(argc, argv, error)) {
547 InitError(strprintf(Untranslated("Error parsing command line arguments: %s"), error));
548 // Create a message box, because the gui has neither been created nor has subscribed to core signals
549 QMessageBox::critical(nullptr, PACKAGE_NAME,
550 // message cannot be translated because translations have not been initialized
551 QString::fromStdString("Error parsing command line arguments: %1.").arg(QString::fromStdString(error)));
552 return EXIT_FAILURE;
553 }
554
555 // Error out when loose non-argument tokens are encountered on command line
556 // However, allow BIP-21 URIs only if no options follow
557 bool payment_server_token_seen = false;
558 for (int i = 1; i < argc; i++) {
559 QString arg(argv[i]);
560 bool invalid_token = !arg.startsWith("-");
561#ifdef ENABLE_WALLET
562 if (arg.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) {
563 invalid_token &= false;
564 payment_server_token_seen = true;
565 }
566#endif
567 if (payment_server_token_seen && arg.startsWith("-")) {
568 InitError(Untranslated(strprintf("Options ('%s') cannot follow a BIP-21 payment URI", argv[i])));
569 QMessageBox::critical(nullptr, PACKAGE_NAME,
570 // message cannot be translated because translations have not been initialized
571 QString::fromStdString("Options ('%1') cannot follow a BIP-21 payment URI").arg(QString::fromStdString(argv[i])));
572 return EXIT_FAILURE;
573 }
574 if (invalid_token) {
575 InitError(Untranslated(strprintf("Command line contains unexpected token '%s', see bitcoin-qt -h for a list of options.", argv[i])));
576 QMessageBox::critical(nullptr, PACKAGE_NAME,
577 // message cannot be translated because translations have not been initialized
578 QString::fromStdString("Command line contains unexpected token '%1', see bitcoin-qt -h for a list of options.").arg(QString::fromStdString(argv[i])));
579 return EXIT_FAILURE;
580 }
581 }
582
583 // Now that the QApplication is setup and we have parsed our parameters, we can set the platform style
584 app.setupPlatformStyle();
585
587 // must be set before OptionsModel is initialized or translations are loaded,
588 // as it is used to locate QSettings
589 QApplication::setOrganizationName(QAPP_ORG_NAME);
590 QApplication::setOrganizationDomain(QAPP_ORG_DOMAIN);
591 QApplication::setApplicationName(QAPP_APP_NAME_DEFAULT);
592
594 // Now that QSettings are accessible, initialize translations
595 QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
596 initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator);
597
598 // Show help message immediately after parsing command-line options (for "-lang") and setting locale,
599 // but before showing splash screen.
600 if (HelpRequested(gArgs) || gArgs.IsArgSet("-version")) {
601 HelpMessageDialog help(nullptr, gArgs.IsArgSet("-version"));
602 help.showOrPrint();
603 return EXIT_SUCCESS;
604 }
605
606 // Install global event filter that makes sure that long tooltips can be word-wrapped
607 app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
608
610 // User language is set up: pick a data directory
611 bool did_show_intro = false;
612 int64_t prune_MiB = 0; // Intro dialog prune configuration
613 // Gracefully exit if the user cancels
614 if (!Intro::showIfNeeded(did_show_intro, prune_MiB)) return EXIT_SUCCESS;
615
618 // - Do not call gArgs.GetDataDirNet() before this step finishes
619 // - Do not call Params() before this step
620 // - QSettings() will use the new application name after this, resulting in network-specific settings
621 // - Needs to be done before createOptionsModel
622 if (auto error = common::InitConfig(gArgs, ErrorSettingsRead)) {
623 InitError(error->message, error->details);
624 if (error->status == common::ConfigStatus::FAILED_WRITE) {
625 // Show a custom error message to provide more information in the
626 // case of a datadir write error.
627 ErrorSettingsWrite(error->message, error->details);
628 } else if (error->status != common::ConfigStatus::ABORTED) {
629 // Show a generic message in other cases, and no additional error
630 // message in the case of a read error if the user decided to abort.
631 QMessageBox::critical(nullptr, PACKAGE_NAME, QObject::tr("Error: %1").arg(QString::fromStdString(error->message.translated)));
632 }
633 return EXIT_FAILURE;
634 }
635#ifdef ENABLE_WALLET
636 // Parse URIs on command line
638#endif
639
640 QScopedPointer<const NetworkStyle> networkStyle(NetworkStyle::instantiate(Params().GetChainType()));
641 assert(!networkStyle.isNull());
642 // Allow for separate UI settings for testnets
643 QApplication::setApplicationName(networkStyle->getAppName());
644 // Re-initialize translations after changing application name (language in network-specific settings can be different)
645 initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator);
646
647#ifdef ENABLE_WALLET
649 // - Do this early as we don't want to bother initializing if we are just calling IPC
650 // - Do this *after* setting up the data directory, as the data directory hash is used in the name
651 // of the server.
652 // - Do this after creating app and setting up translations, so errors are
653 // translated properly.
655 exit(EXIT_SUCCESS);
656
657 // Start up the payment server early, too, so impatient users that click on
658 // bitcoin: links repeatedly have their payment requests routed to this process:
660 app.createPaymentServer();
661 }
662#endif // ENABLE_WALLET
663
665 // Install global event filter that makes sure that out-of-focus labels do not contain text cursor.
666 app.installEventFilter(new GUIUtil::LabelOutOfFocusEventFilter(&app));
667#if defined(Q_OS_WIN)
668 // Install global event filter for processing Windows session related Windows messages (WM_QUERYENDSESSION and WM_ENDSESSION)
669 // Note: it is safe to call app.node() in the lambda below despite the fact
670 // that app.createNode() hasn't been called yet, because native events will
671 // not be processed until the Qt event loop is executed.
672 qApp->installNativeEventFilter(new WinShutdownMonitor([&app] { app.node().startShutdown(); }));
673#endif
674 // Install qDebug() message handler to route to debug.log
675 qInstallMessageHandler(DebugMessageHandler);
676 // Allow parameter interaction before we create the options model
677 app.parameterSetup();
679
680 if (gArgs.GetBoolArg("-splash", DEFAULT_SPLASHSCREEN) && !gArgs.GetBoolArg("-min", false))
681 app.createSplashScreen(networkStyle.data());
682
683 app.createNode(*init);
684
685 // Load GUI settings from QSettings
686 if (!app.createOptionsModel(gArgs.GetBoolArg("-resetguisettings", false))) {
687 return EXIT_FAILURE;
688 }
689
690 if (did_show_intro) {
691 // Store intro dialog settings other than datadir (network specific)
692 app.InitPruneSetting(prune_MiB);
693 }
694
695 try
696 {
697 app.createWindow(networkStyle.data());
698 // Perform base initialization before spinning up initialization/shutdown thread
699 // This is acceptable because this function only contains steps that are quick to execute,
700 // so the GUI thread won't be held up.
701 if (app.baseInitialize()) {
702 app.requestInitialize();
703#if defined(Q_OS_WIN)
704 WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely…").arg(PACKAGE_NAME), (HWND)app.getMainWinId());
705#endif
706 app.exec();
707 } else {
708 // A dialog with detailed error will have been shown by InitError()
709 return EXIT_FAILURE;
710 }
711 } catch (const std::exception& e) {
712 PrintExceptionContinue(&e, "Runaway exception");
713 app.handleRunawayException(QString::fromStdString(app.node().getWarnings().translated));
714 } catch (...) {
715 PrintExceptionContinue(nullptr, "Runaway exception");
716 app.handleRunawayException(QString::fromStdString(app.node().getWarnings().translated));
717 }
718 return app.node().getExitStatus();
719}
int64_t CAmount
Amount in satoshis (Can be negative)
Definition amount.h:12
bool HelpRequested(const ArgsManager &args)
Definition args.cpp:660
ArgsManager gArgs
Definition args.cpp:41
#define PACKAGE_NAME
#define PACKAGE_BUGREPORT
SetupEnvironment()
Definition system.cpp:59
return EXIT_SUCCESS
static bool ErrorSettingsRead(const bilingual_str &error, const std::vector< std::string > &details)
Definition bitcoin.cpp:178
static void RegisterMetaTypes()
Definition bitcoin.cpp:90
static int qt_argc
Definition bitcoin.cpp:221
static QString GetLangTerritory()
Definition bitcoin.cpp:116
int GuiMain(int argc, char *argv[])
Definition bitcoin.cpp:503
static void ErrorSettingsWrite(const bilingual_str &error, const std::vector< std::string > &details)
Definition bitcoin.cpp:197
static void SetupUIArgs(ArgsManager &argsman)
Definition bitcoin.cpp:493
static const char * qt_argv
Definition bitcoin.cpp:222
static void initTranslations(QTranslator &qtTranslatorBase, QTranslator &qtTranslator, QTranslator &translatorBase, QTranslator &translator)
Set up translations.
Definition bitcoin.cpp:132
void DebugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
Definition bitcoin.cpp:211
const CChainParams & Params()
Return the currently selected parameters.
@ ALLOW_ANY
disable validation
Definition args.h:104
@ DEBUG_ONLY
Definition args.h:112
bool ParseParameters(int argc, const char *const argv[], std::string &error)
Definition args.cpp:178
bool GetSettingsPath(fs::path *filepath=nullptr, bool temp=false, bool backup=false) const
Get settings file path, or return false if read-write settings were disabled with -nosettings.
Definition args.cpp:375
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition args.cpp:370
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition args.cpp:456
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn't already have a value.
Definition args.cpp:537
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition args.cpp:506
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
Definition args.cpp:563
Main Bitcoin application object.
Definition bitcoin.h:35
bool createOptionsModel(bool resetSettings)
Create options model.
Definition bitcoin.cpp:262
std::optional< InitExecutor > m_executor
Definition bitcoin.h:93
ClientModel * clientModel
Definition bitcoin.h:95
void InitPruneSetting(int64_t prune_MiB)
Initialize prune setting.
Definition bitcoin.cpp:341
void createSplashScreen(const NetworkStyle *networkStyle)
Create splash screen.
Definition bitcoin.cpp:297
void requestShutdown()
Request core shutdown.
Definition bitcoin.cpp:353
SplashScreen * m_splash
Definition bitcoin.h:104
void windowShown(BitcoinGUI *window)
void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info)
Definition bitcoin.cpp:403
interfaces::Node & node() const
Definition bitcoin.h:69
void createNode(interfaces::Init &init)
Create or spawn node.
Definition bitcoin.cpp:304
QTimer * pollShutdownTimer
Definition bitcoin.h:97
BitcoinGUI * window
Definition bitcoin.h:96
const PlatformStyle * platformStyle
Definition bitcoin.h:102
bool baseInitialize()
Basic initialization, before starting initialization/shutdown thread. Return true on success.
Definition bitcoin.cpp:311
void createWindow(const NetworkStyle *networkStyle)
Create main window.
Definition bitcoin.cpp:284
void parameterSetup()
parameter interaction/setup based on rules
Definition bitcoin.cpp:331
void handleRunawayException(const QString &message)
Handle runaway exceptions. Shows a message box with the problem and quits the program.
Definition bitcoin.cpp:456
OptionsModel * optionsModel
Definition bitcoin.h:94
bool event(QEvent *e) override
Definition bitcoin.cpp:483
void setupPlatformStyle()
Setup platform style.
Definition bitcoin.cpp:232
std::unique_ptr< interfaces::Node > m_node
Definition bitcoin.h:105
std::unique_ptr< QWidget > shutdownWindow
Definition bitcoin.h:103
void requestInitialize()
Request core initialization.
Definition bitcoin.cpp:346
WId getMainWinId() const
Get window identifier of QMainWindow (BitcoinGUI)
Definition bitcoin.cpp:475
void handleNonFatalException(const QString &message)
A helper function that shows a message box with details about a non-fatal exception.
Definition bitcoin.cpp:465
Bitcoin GUI main class.
Definition bitcoingui.h:68
static const std::string DEFAULT_UIPLATFORM
Definition bitcoingui.h:72
void setClientModel(ClientModel *clientModel=nullptr, interfaces::BlockAndHeaderTipInfo *tip_info=nullptr)
Set the client model.
void receivedURI(const QString &uri)
Signal raised when a URI was entered or dragged to the GUI.
void unsubscribeFromCoreSignals()
Disconnect core signals from GUI client.
bool hasTrayIcon() const
Get the tray icon status.
Definition bitcoingui.h:100
void detectShutdown()
called by a timer to check if shutdown has been requested
void message(const QString &title, QString message, unsigned int style, bool *ret=nullptr, const QString &detailed_message=QString())
Notify the user of an event from the core network or transaction handling code.
Model for Bitcoin network client.
Definition clientmodel.h:57
OptionsModel * getOptionsModel()
Qt event filter that intercepts QEvent::FocusOut events for QLabel objects, and resets their ‘textInt...
Definition guiutil.h:208
Qt event filter that intercepts ToolTipChange events, and replaces the tooltip with a rich text repre...
Definition guiutil.h:188
"Help message" dialog box
void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info)
void runawayException(const QString &message)
static bool showIfNeeded(bool &did_show_intro, int64_t &prune_MiB)
Determine data directory.
Definition intro.cpp:205
static const NetworkStyle * instantiate(const ChainType networkId)
Get style associated with provided network id, or 0 if not known.
Interface from Qt to configuration data structure for Bitcoin client.
void SetPruneTargetGB(int prune_target_gb)
bool Init(bilingual_str &error)
bool getMinimizeToTray() const
static bool ipcSendCommandLine()
void message(const QString &title, const QString &message, unsigned int style)
static void ipcParseCommandLine(int argc, char *argv[])
void receivedPaymentRequest(SendCoinsRecipient)
void handleURIOrFile(const QString &s)
const QString & getName() const
static const PlatformStyle * instantiate(const QString &platformId)
Get style associated with provided platform name, or 0 if not known.
static QWidget * showShutdownWindow(QMainWindow *window)
Class for the splashscreen with information of the running client.
void setNode(interfaces::Node &node)
Controller between interfaces::Node, WalletModel instances and the GUI.
static bool isWalletEnabled()
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition fs.h:33
Initial interface created when a process is first started, and used to give and get access to other i...
Definition init.h:31
virtual bool baseInitialize()=0
Initialize app dependencies.
virtual bilingual_str getWarnings()=0
Get warnings.
virtual void startShutdown()=0
Start shutdown.
virtual int getExitStatus()=0
Get exit status.
256-bit opaque blob.
Definition uint256.h:178
SyncType
Definition clientmodel.h:42
void PrintExceptionContinue(const std::exception *pex, std::string_view thread_name)
Definition exception.cpp:36
static constexpr auto SHUTDOWN_POLLING_DELAY
static const int TOOLTIP_WRAP_THRESHOLD
#define QAPP_ORG_NAME
static const bool DEFAULT_SPLASHSCREEN
#define QAPP_APP_NAME_DEFAULT
#define QAPP_ORG_DOMAIN
void InitLogging(const ArgsManager &args)
Initialize global loggers.
Definition init.cpp:828
void SetupServerArgs(ArgsManager &argsman)
Register all arguments with the ArgsManager.
Definition init.cpp:444
void InitParameterInteraction(ArgsManager &args)
Parameter interaction: change current parameters depending on various rules.
Definition init.cpp:736
CClientUIInterface uiInterface
bool InitError(const bilingual_str &str)
Show error message.
static const bool DEFAULT_CHOOSE_DATADIR
Definition intro.h:12
#define LogPrint(category,...)
Definition logging.h:293
#define LogPrintf(...)
Definition logging.h:274
@ QT
Definition logging.h:61
QString MakeHtmlLink(const QString &source, const QString &link)
Replaces a plain text link with an HTML tagged one.
Definition guiutil.cpp:986
void LogQtInfo()
Writes to debug.log short info about the used Qt and the host system.
Definition guiutil.cpp:920
void LoadFont(const QString &file_name)
Loads the font from the file specified by file_name, aborts if it fails.
Definition guiutil.cpp:291
@ ABORTED
Aborted by user.
@ FAILED_WRITE
Failed to write settings.json.
std::optional< ConfigError > InitConfig(ArgsManager &args, SettingsAbortFn settings_abort_fn)
Definition init.cpp:18
static auto quoted(const std::string &s)
Definition fs.h:95
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition fs.h:151
std::unique_ptr< Init > MakeGuiInit(int argc, char *argv[])
Return implementation of Init interface for the gui process.
std::string MakeUnorderedList(const std::vector< std::string > &items)
Create an unordered multi-line list of items.
Definition string.h:136
void ThreadSetInternalName(const std::string &)
Set the internal (in-memory) name of the current thread only.
AddressPurpose
Address purpose field that has been been stored with wallet sending and receiving addresses since BIP...
Definition types.h:61
bool noui_ThreadSafeQuestion(const bilingual_str &, const std::string &message, const std::string &caption, unsigned int style)
Non-GUI handler, which logs and prints questions.
Definition noui.cpp:50
void noui_InitMessage(const std::string &message)
Non-GUI handler, which only logs a message.
Definition noui.cpp:55
bool noui_ThreadSafeMessageBox(const bilingual_str &message, const std::string &caption, unsigned int style)
Non-GUI handler, which logs and prints messages.
Definition noui.cpp:22
static int PruneMiBtoGB(int64_t mib)
Convert configured prune target MiB to displayed GB.
QT_END_NAMESPACE const QString BITCOIN_IPC_PREFIX
static RPCHelpMan help()
Definition server.cpp:143
Bilingual messages:
Definition translation.h:18
std::string translated
Definition translation.h:20
std::string original
Definition translation.h:19
Block and header tip information.
Definition node.h:50
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
bilingual_str Untranslated(std::string original)
Mark a bilingual_str as untranslated.
Definition translation.h:48
assert(!tx.IsCoinBase())
SynchronizationState
Current sync state passed to tip changed callbacks.
Definition validation.h:82
is a home for public enum and struct type definitions that are used by internally by wallet code,...