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