Bitcoin Core  26.99.0
P2P Digital Currency
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 #if defined(HAVE_CONFIG_H)
7 #endif
8 
9 #include <qt/bitcoin.h>
10 
11 #include <chainparams.h>
12 #include <common/args.h>
13 #include <common/init.h>
14 #include <common/system.h>
15 #include <init.h>
16 #include <interfaces/handler.h>
17 #include <interfaces/init.h>
18 #include <interfaces/node.h>
19 #include <logging.h>
20 #include <node/context.h>
21 #include <node/interface_ui.h>
22 #include <noui.h>
23 #include <qt/bitcoingui.h>
24 #include <qt/clientmodel.h>
25 #include <qt/guiconstants.h>
26 #include <qt/guiutil.h>
27 #include <qt/initexecutor.h>
28 #include <qt/intro.h>
29 #include <qt/networkstyle.h>
30 #include <qt/optionsmodel.h>
31 #include <qt/platformstyle.h>
32 #include <qt/splashscreen.h>
33 #include <qt/utilitydialog.h>
34 #include <qt/winshutdownmonitor.h>
35 #include <uint256.h>
36 #include <util/exception.h>
37 #include <util/string.h>
38 #include <util/threadnames.h>
39 #include <util/translation.h>
40 #include <validation.h>
41 
42 #ifdef ENABLE_WALLET
43 #include <qt/paymentserver.h>
44 #include <qt/walletcontroller.h>
45 #include <qt/walletmodel.h>
46 #include <wallet/types.h>
47 #endif // ENABLE_WALLET
48 
49 #include <boost/signals2/connection.hpp>
50 #include <chrono>
51 #include <memory>
52 
53 #include <QApplication>
54 #include <QDebug>
55 #include <QLatin1String>
56 #include <QLibraryInfo>
57 #include <QLocale>
58 #include <QMessageBox>
59 #include <QSettings>
60 #include <QThread>
61 #include <QTimer>
62 #include <QTranslator>
63 #include <QWindow>
64 
65 #if defined(QT_STATICPLUGIN)
66 #include <QtPlugin>
67 #if defined(QT_QPA_PLATFORM_XCB)
68 Q_IMPORT_PLUGIN(QXcbIntegrationPlugin);
69 #elif defined(QT_QPA_PLATFORM_WINDOWS)
70 Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin);
71 Q_IMPORT_PLUGIN(QWindowsVistaStylePlugin);
72 #elif defined(QT_QPA_PLATFORM_COCOA)
73 Q_IMPORT_PLUGIN(QCocoaIntegrationPlugin);
74 Q_IMPORT_PLUGIN(QMacStylePlugin);
75 #elif defined(QT_QPA_PLATFORM_ANDROID)
76 Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin)
77 #endif
78 #endif
79 
80 // Declare meta types used for QMetaObject::invokeMethod
81 Q_DECLARE_METATYPE(bool*)
82 Q_DECLARE_METATYPE(CAmount)
83 Q_DECLARE_METATYPE(SynchronizationState)
84 Q_DECLARE_METATYPE(SyncType)
85 Q_DECLARE_METATYPE(uint256)
86 #ifdef ENABLE_WALLET
87 Q_DECLARE_METATYPE(wallet::AddressPurpose)
88 #endif // ENABLE_WALLET
89 
90 static 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 
116 static 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 
132 static 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 
178 static 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 
197 static 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 */
211 void 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 
221 static int qt_argc = 1;
222 static 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
256 void BitcoinApplication::createPaymentServer()
257 {
258  paymentServer = new PaymentServer(this);
259 }
260 #endif
261 
263 {
264  optionsModel = new OptionsModel(node(), this);
265  if (resetSettings) {
266  optionsModel->Reset();
267  }
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 {
299  assert(!m_splash);
300  m_splash = new SplashScreen(networkStyle);
301  m_splash->show();
302 }
303 
305 {
306  assert(!m_node);
307  m_node = init.makeNode();
309 }
310 
312 {
313  return node().baseInitialize();
314 }
315 
317 {
318  assert(!m_executor);
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.
374  node().startShutdown();
375  // Unsetting the client model can cause the current thread to wait for node
376  // to complete an operation, like wait for a RPC execution to complete.
377  window->setClientModel(nullptr);
378  pollShutdownTimer->stop();
379 
380 #ifdef ENABLE_WALLET
381  // Delete wallet controller here manually, instead of relying on Qt object
382  // tracking (https://doc.qt.io/qt-5/objecttrees.html). This makes sure
383  // walletmodel m_handle_* notification handlers are deleted before wallets
384  // are unloaded, which can simplify wallet implementations. It also avoids
385  // these notifications having to be handled while GUI objects are being
386  // destroyed, making GUI code less fragile as well.
387  delete m_wallet_controller;
388  m_wallet_controller = nullptr;
389 #endif // ENABLE_WALLET
390 
391  delete clientModel;
392  clientModel = nullptr;
393 
394  // Request shutdown from core thread
395  Q_EMIT requestedShutdown();
396 }
397 
399 {
400  qDebug() << __func__ << ": Initialization result: " << success;
401 
402  if (success) {
403  delete m_splash;
404  m_splash = nullptr;
405 
406  // Log this only after AppInitMain finishes, as then logging setup is guaranteed complete
407  qInfo() << "Platform customization:" << platformStyle->getName();
409  window->setClientModel(clientModel, &tip_info);
410 
411  // If '-min' option passed, start window minimized (iconified) or minimized to tray
412  bool start_minimized = gArgs.GetBoolArg("-min", false);
413 #ifdef ENABLE_WALLET
415  m_wallet_controller = new WalletController(*clientModel, platformStyle, this);
416  window->setWalletController(m_wallet_controller, /*show_loading_minimized=*/start_minimized);
417  if (paymentServer) {
418  paymentServer->setOptionsModel(optionsModel);
419  }
420  }
421 #endif // ENABLE_WALLET
422 
423  // Show or minimize window
424  if (!start_minimized) {
425  window->show();
427  // do nothing as the window is managed by the tray icon
428  } else {
429  window->showMinimized();
430  }
431  Q_EMIT windowShown(window);
432 
433 #ifdef ENABLE_WALLET
434  // Now that initialization/startup is done, process any command-line
435  // bitcoin: URIs or payment requests:
436  if (paymentServer) {
437  connect(paymentServer, &PaymentServer::receivedPaymentRequest, window, &BitcoinGUI::handlePaymentRequest);
439  connect(paymentServer, &PaymentServer::message, [this](const QString& title, const QString& message, unsigned int style) {
440  window->message(title, message, style);
441  });
442  QTimer::singleShot(100ms, paymentServer, &PaymentServer::uiReady);
443  }
444 #endif
446  } else {
447  requestShutdown();
448  }
449 }
450 
451 void BitcoinApplication::handleRunawayException(const QString &message)
452 {
453  QMessageBox::critical(
454  nullptr, tr("Runaway exception"),
455  tr("A fatal error occurred. %1 can no longer continue safely and will quit.").arg(PACKAGE_NAME) +
456  QLatin1String("<br><br>") + GUIUtil::MakeHtmlLink(message, PACKAGE_BUGREPORT));
457  ::exit(EXIT_FAILURE);
458 }
459 
461 {
462  assert(QThread::currentThread() == thread());
463  QMessageBox::warning(
464  nullptr, tr("Internal error"),
465  tr("An internal error occurred. %1 will attempt to continue safely. This is "
466  "an unexpected bug which can be reported as described below.").arg(PACKAGE_NAME) +
467  QLatin1String("<br><br>") + GUIUtil::MakeHtmlLink(message, PACKAGE_BUGREPORT));
468 }
469 
471 {
472  if (!window)
473  return 0;
474 
475  return window->winId();
476 }
477 
479 {
480  if (e->type() == QEvent::Quit) {
481  requestShutdown();
482  return true;
483  }
484 
485  return QApplication::event(e);
486 }
487 
488 static void SetupUIArgs(ArgsManager& argsman)
489 {
490  argsman.AddArg("-choosedatadir", strprintf("Choose data directory on startup (default: %u)", DEFAULT_CHOOSE_DATADIR), ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
491  argsman.AddArg("-lang=<lang>", "Set language, for example \"de_DE\" (default: system locale)", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
492  argsman.AddArg("-min", "Start minimized", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
493  argsman.AddArg("-resetguisettings", "Reset all settings changed in the GUI", ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
494  argsman.AddArg("-splash", strprintf("Show splash screen on startup (default: %u)", DEFAULT_SPLASHSCREEN), ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
495  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);
496 }
497 
498 int GuiMain(int argc, char* argv[])
499 {
500 #ifdef WIN32
501  common::WinCmdLineArgs winArgs;
502  std::tie(argc, argv) = winArgs.get();
503 #endif
504 
505  std::unique_ptr<interfaces::Init> init = interfaces::MakeGuiInit(argc, argv);
506 
509 
510  // Subscribe to global signals from core
511  boost::signals2::scoped_connection handler_message_box = ::uiInterface.ThreadSafeMessageBox_connect(noui_ThreadSafeMessageBox);
512  boost::signals2::scoped_connection handler_question = ::uiInterface.ThreadSafeQuestion_connect(noui_ThreadSafeQuestion);
513  boost::signals2::scoped_connection handler_init_message = ::uiInterface.InitMessage_connect(noui_InitMessage);
514 
515  // Do not refer to data directory yet, this can be overridden by Intro::pickDataDirectory
516 
518  Q_INIT_RESOURCE(bitcoin);
519  Q_INIT_RESOURCE(bitcoin_locale);
520 
521 #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
522  // Generate high-dpi pixmaps
523  QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
524  QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
525 #endif
526 
527 #if defined(QT_QPA_PLATFORM_ANDROID)
528  QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
529  QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
530  QApplication::setAttribute(Qt::AA_DontUseNativeDialogs);
531 #endif
532 
533  BitcoinApplication app;
534  GUIUtil::LoadFont(QStringLiteral(":/fonts/monospace"));
535 
537  // Command-line options take precedence:
540  std::string error;
541  if (!gArgs.ParseParameters(argc, argv, error)) {
542  InitError(strprintf(Untranslated("Error parsing command line arguments: %s"), error));
543  // Create a message box, because the gui has neither been created nor has subscribed to core signals
544  QMessageBox::critical(nullptr, PACKAGE_NAME,
545  // message cannot be translated because translations have not been initialized
546  QString::fromStdString("Error parsing command line arguments: %1.").arg(QString::fromStdString(error)));
547  return EXIT_FAILURE;
548  }
549 
550  // Error out when loose non-argument tokens are encountered on command line
551  // However, allow BIP-21 URIs only if no options follow
552  bool payment_server_token_seen = false;
553  for (int i = 1; i < argc; i++) {
554  QString arg(argv[i]);
555  bool invalid_token = !arg.startsWith("-");
556 #ifdef ENABLE_WALLET
557  if (arg.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) {
558  invalid_token &= false;
559  payment_server_token_seen = true;
560  }
561 #endif
562  if (payment_server_token_seen && arg.startsWith("-")) {
563  InitError(Untranslated(strprintf("Options ('%s') cannot follow a BIP-21 payment URI", argv[i])));
564  QMessageBox::critical(nullptr, PACKAGE_NAME,
565  // message cannot be translated because translations have not been initialized
566  QString::fromStdString("Options ('%1') cannot follow a BIP-21 payment URI").arg(QString::fromStdString(argv[i])));
567  return EXIT_FAILURE;
568  }
569  if (invalid_token) {
570  InitError(Untranslated(strprintf("Command line contains unexpected token '%s', see bitcoin-qt -h for a list of options.", argv[i])));
571  QMessageBox::critical(nullptr, PACKAGE_NAME,
572  // message cannot be translated because translations have not been initialized
573  QString::fromStdString("Command line contains unexpected token '%1', see bitcoin-qt -h for a list of options.").arg(QString::fromStdString(argv[i])));
574  return EXIT_FAILURE;
575  }
576  }
577 
578  // Now that the QApplication is setup and we have parsed our parameters, we can set the platform style
579  app.setupPlatformStyle();
580 
582  // must be set before OptionsModel is initialized or translations are loaded,
583  // as it is used to locate QSettings
584  QApplication::setOrganizationName(QAPP_ORG_NAME);
585  QApplication::setOrganizationDomain(QAPP_ORG_DOMAIN);
586  QApplication::setApplicationName(QAPP_APP_NAME_DEFAULT);
587 
589  // Now that QSettings are accessible, initialize translations
590  QTranslator qtTranslatorBase, qtTranslator, translatorBase, translator;
591  initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator);
592 
593  // Show help message immediately after parsing command-line options (for "-lang") and setting locale,
594  // but before showing splash screen.
595  if (HelpRequested(gArgs) || gArgs.IsArgSet("-version")) {
596  HelpMessageDialog help(nullptr, gArgs.IsArgSet("-version"));
597  help.showOrPrint();
598  return EXIT_SUCCESS;
599  }
600 
601  // Install global event filter that makes sure that long tooltips can be word-wrapped
602  app.installEventFilter(new GUIUtil::ToolTipToRichTextFilter(TOOLTIP_WRAP_THRESHOLD, &app));
603 
605  // User language is set up: pick a data directory
606  bool did_show_intro = false;
607  int64_t prune_MiB = 0; // Intro dialog prune configuration
608  // Gracefully exit if the user cancels
609  if (!Intro::showIfNeeded(did_show_intro, prune_MiB)) return EXIT_SUCCESS;
610 
613  // - Do not call gArgs.GetDataDirNet() before this step finishes
614  // - Do not call Params() before this step
615  // - QSettings() will use the new application name after this, resulting in network-specific settings
616  // - Needs to be done before createOptionsModel
618  InitError(error->message, error->details);
619  if (error->status == common::ConfigStatus::FAILED_WRITE) {
620  // Show a custom error message to provide more information in the
621  // case of a datadir write error.
622  ErrorSettingsWrite(error->message, error->details);
623  } else if (error->status != common::ConfigStatus::ABORTED) {
624  // Show a generic message in other cases, and no additional error
625  // message in the case of a read error if the user decided to abort.
626  QMessageBox::critical(nullptr, PACKAGE_NAME, QObject::tr("Error: %1").arg(QString::fromStdString(error->message.translated)));
627  }
628  return EXIT_FAILURE;
629  }
630 #ifdef ENABLE_WALLET
631  // Parse URIs on command line
633 #endif
634 
635  QScopedPointer<const NetworkStyle> networkStyle(NetworkStyle::instantiate(Params().GetChainType()));
636  assert(!networkStyle.isNull());
637  // Allow for separate UI settings for testnets
638  QApplication::setApplicationName(networkStyle->getAppName());
639  // Re-initialize translations after changing application name (language in network-specific settings can be different)
640  initTranslations(qtTranslatorBase, qtTranslator, translatorBase, translator);
641 
642 #ifdef ENABLE_WALLET
644  // - Do this early as we don't want to bother initializing if we are just calling IPC
645  // - Do this *after* setting up the data directory, as the data directory hash is used in the name
646  // of the server.
647  // - Do this after creating app and setting up translations, so errors are
648  // translated properly.
650  exit(EXIT_SUCCESS);
651 
652  // Start up the payment server early, too, so impatient users that click on
653  // bitcoin: links repeatedly have their payment requests routed to this process:
655  app.createPaymentServer();
656  }
657 #endif // ENABLE_WALLET
658 
660  // Install global event filter that makes sure that out-of-focus labels do not contain text cursor.
661  app.installEventFilter(new GUIUtil::LabelOutOfFocusEventFilter(&app));
662 #if defined(Q_OS_WIN)
663  // Install global event filter for processing Windows session related Windows messages (WM_QUERYENDSESSION and WM_ENDSESSION)
664  qApp->installNativeEventFilter(new WinShutdownMonitor());
665 #endif
666  // Install qDebug() message handler to route to debug.log
667  qInstallMessageHandler(DebugMessageHandler);
668  // Allow parameter interaction before we create the options model
669  app.parameterSetup();
671 
672  if (gArgs.GetBoolArg("-splash", DEFAULT_SPLASHSCREEN) && !gArgs.GetBoolArg("-min", false))
673  app.createSplashScreen(networkStyle.data());
674 
675  app.createNode(*init);
676 
677  // Load GUI settings from QSettings
678  if (!app.createOptionsModel(gArgs.GetBoolArg("-resetguisettings", false))) {
679  return EXIT_FAILURE;
680  }
681 
682  if (did_show_intro) {
683  // Store intro dialog settings other than datadir (network specific)
684  app.InitPruneSetting(prune_MiB);
685  }
686 
687  try
688  {
689  app.createWindow(networkStyle.data());
690  // Perform base initialization before spinning up initialization/shutdown thread
691  // This is acceptable because this function only contains steps that are quick to execute,
692  // so the GUI thread won't be held up.
693  if (app.baseInitialize()) {
694  app.requestInitialize();
695 #if defined(Q_OS_WIN)
696  WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely…").arg(PACKAGE_NAME), (HWND)app.getMainWinId());
697 #endif
698  app.exec();
699  } else {
700  // A dialog with detailed error will have been shown by InitError()
701  return EXIT_FAILURE;
702  }
703  } catch (const std::exception& e) {
704  PrintExceptionContinue(&e, "Runaway exception");
705  app.handleRunawayException(QString::fromStdString(app.node().getWarnings().translated));
706  } catch (...) {
707  PrintExceptionContinue(nullptr, "Runaway exception");
708  app.handleRunawayException(QString::fromStdString(app.node().getWarnings().translated));
709  }
710  return app.node().getExitStatus();
711 }
int64_t CAmount
Amount in satoshis (Can be negative)
Definition: amount.h:12
bool HelpRequested(const ArgsManager &args)
Definition: args.cpp:659
ArgsManager gArgs
Definition: args.cpp:41
#define PACKAGE_NAME
#define PACKAGE_BUGREPORT
SetupEnvironment()
Definition: system.cpp:55
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:498
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:488
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:177
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:374
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: args.cpp:369
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: args.cpp:455
bool SoftSetBoolArg(const std::string &strArg, bool fValue)
Set a boolean argument if it doesn't already have a value.
Definition: args.cpp:536
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: args.cpp:505
void AddArg(const std::string &name, const std::string &help, unsigned int flags, const OptionsCategory &cat)
Add argument.
Definition: args.cpp:562
Main Bitcoin application object.
Definition: bitcoin.h:37
bool createOptionsModel(bool resetSettings)
Create options model.
Definition: bitcoin.cpp:262
std::optional< InitExecutor > m_executor
Definition: bitcoin.h:95
void requestedInitialize()
ClientModel * clientModel
Definition: bitcoin.h:97
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:106
void windowShown(BitcoinGUI *window)
void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info)
Definition: bitcoin.cpp:398
void createNode(interfaces::Init &init)
Create or spawn node.
Definition: bitcoin.cpp:304
QTimer * pollShutdownTimer
Definition: bitcoin.h:99
BitcoinGUI * window
Definition: bitcoin.h:98
const PlatformStyle * platformStyle
Definition: bitcoin.h:104
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:451
OptionsModel * optionsModel
Definition: bitcoin.h:96
bool event(QEvent *e) override
Definition: bitcoin.cpp:478
void setupPlatformStyle()
Setup platform style.
Definition: bitcoin.cpp:232
std::unique_ptr< interfaces::Node > m_node
Definition: bitcoin.h:107
std::unique_ptr< QWidget > shutdownWindow
Definition: bitcoin.h:105
void requestInitialize()
Request core initialization.
Definition: bitcoin.cpp:346
WId getMainWinId() const
Get window identifier of QMainWindow (BitcoinGUI)
Definition: bitcoin.cpp:470
void handleNonFatalException(const QString &message)
A helper function that shows a message box with details about a non-fatal exception.
Definition: bitcoin.cpp:460
interfaces::Node & node() const
Definition: bitcoin.h:71
Bitcoin GUI main class.
Definition: bitcoingui.h:70
static const std::string DEFAULT_UIPLATFORM
Definition: bitcoingui.h:74
void setClientModel(ClientModel *clientModel=nullptr, interfaces::BlockAndHeaderTipInfo *tip_info=nullptr)
Set the client model.
Definition: bitcoingui.cpp:601
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:102
void detectShutdown()
called by a timer to check if ShutdownRequested() has been set
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.
void quitRequested()
Model for Bitcoin network client.
Definition: clientmodel.h:54
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
Definition: utilitydialog.h:21
void initialize()
void initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info)
void runawayException(const QString &message)
void shutdownResult()
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.
Definition: optionsmodel.h:41
void SetPruneTargetGB(int prune_target_gb)
bool Init(bilingual_str &error)
bool getMinimizeToTray() const
Definition: optionsmodel.h:92
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
Definition: platformstyle.h:19
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.
Definition: splashscreen.h:27
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:31
Initial interface created when a process is first started, and used to give and get access to other i...
Definition: init.h:30
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:106
SyncType
Definition: clientmodel.h:39
void PrintExceptionContinue(const std::exception *pex, std::string_view thread_name)
Definition: exception.cpp:36
static constexpr auto SHUTDOWN_POLLING_DELAY
Definition: guiconstants.h:17
static const int TOOLTIP_WRAP_THRESHOLD
Definition: guiconstants.h:44
#define QAPP_ORG_NAME
Definition: guiconstants.h:49
static const bool DEFAULT_SPLASHSCREEN
Definition: guiconstants.h:25
#define QAPP_APP_NAME_DEFAULT
Definition: guiconstants.h:51
#define QAPP_ORG_DOMAIN
Definition: guiconstants.h:50
void InitLogging(const ArgsManager &args)
Initialize global loggers.
Definition: init.cpp:786
void SetupServerArgs(ArgsManager &argsman)
Register all arguments with the ArgsManager.
Definition: init.cpp:415
void InitParameterInteraction(ArgsManager &args)
Parameter interaction: change current parameters depending on various rules.
Definition: init.cpp:694
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:246
bool error(const char *fmt, const Args &... args)
Definition: logging.h:262
#define LogPrintf(...)
Definition: logging.h:237
@ QT
Definition: logging.h:59
QString MakeHtmlLink(const QString &source, const QString &link)
Replaces a plain text link with an HTML tagged one.
Definition: guiutil.cpp:980
void LogQtInfo()
Writes to debug.log short info about the used Qt and the host system.
Definition: guiutil.cpp:909
void LoadFont(const QString &file_name)
Loads the font from the file specified by file_name, aborts if it fails.
Definition: guiutil.cpp:286
@ 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:94
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition: fs.h:150
std::unique_ptr< Init > MakeGuiInit(int argc, char *argv[])
Return implementation of Init interface for the gui process.
Definition: bitcoin-gui.cpp:44
void ThreadSetInternalName(std::string &&)
Set the internal (in-memory) name of the current thread only.
Definition: threadnames.cpp:65
AddressPurpose
Address purpose field that has been been stored with wallet sending and receiving addresses since BIP...
Definition: types.h:60
WalletContext context
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:49
void noui_InitMessage(const std::string &message)
Non-GUI handler, which only logs a message.
Definition: noui.cpp:54
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.
Definition: optionsmodel.h:27
QT_END_NAMESPACE const QString BITCOIN_IPC_PREFIX
static RPCHelpMan help()
Definition: server.cpp:137
std::string MakeUnorderedList(const std::vector< std::string > &items)
Create an unordered multi-line list of items.
Definition: string.h:89
Bilingual messages:
Definition: translation.h:18
std::string translated
Definition: translation.h:20
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...
Definition: tinyformat.h:1162
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:84