diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 31f9afeba7..c1fc5828b8 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #ifdef ENABLE_WALLET @@ -608,10 +609,9 @@ int GuiMain(int argc, char* argv[]) /// 5. Now that settings and translations are available, ask user for data directory // User language is set up: pick a data directory - bool did_show_intro = false; - int64_t prune_MiB = 0; // Intro dialog prune configuration + std::unique_ptr intro; // Gracefully exit if the user cancels - if (!Intro::showIfNeeded(did_show_intro, prune_MiB)) return EXIT_SUCCESS; + if (!Intro::showIfNeeded(intro)) return EXIT_SUCCESS; /// 6-7. Parse bitcoin.conf, determine network, switch to network specific /// options, and create datadir and settings.json. @@ -687,9 +687,10 @@ int GuiMain(int argc, char* argv[]) return EXIT_FAILURE; } - if (did_show_intro) { + if (intro) { // Store intro dialog settings other than datadir (network specific) - app.InitPruneSetting(prune_MiB); + app.InitPruneSetting(intro->getPruneMiB()); + gArgs.ForceSetArg("-assumevalid", intro->getAssumeValid().toStdString()); } try @@ -699,6 +700,13 @@ int GuiMain(int argc, char* argv[]) // This is acceptable because this function only contains steps that are quick to execute, // so the GUI thread won't be held up. if (app.baseInitialize()) { + if (intro) { + // Store intro dialog settings other than datadir (network specific) + common::SettingsValue intro_assumevalid = intro->getAssumeValid().toStdString(); + app.node().context()->chain->overwriteRwSetting("assumevalid", intro_assumevalid); + // We can release the Intro widget now + intro.reset(); + } app.requestInitialize(); #if defined(Q_OS_WIN) WinShutdownMonitor::registerShutdownBlockReason(QObject::tr("%1 didn't yet exit safely…").arg(PACKAGE_NAME), (HWND)app.getMainWinId()); diff --git a/src/qt/bitcoin.h b/src/qt/bitcoin.h index 1423a8bbc6..189910fb7a 100644 --- a/src/qt/bitcoin.h +++ b/src/qt/bitcoin.h @@ -7,6 +7,7 @@ #include // IWYU pragma: keep +#include #include #include diff --git a/src/qt/forms/intro.ui b/src/qt/forms/intro.ui index 074ed42c92..b73bb3f3ad 100644 --- a/src/qt/forms/intro.ui +++ b/src/qt/forms/intro.ui @@ -271,6 +271,64 @@ + + + + + + + The initial synchronisation process can go faster if you skip verification of older transactions. This does, however, require trusting that the "assumed valid" blockchain below is in fact valid. Uncheck this if you want to fully validate the entire blockchain history. + + + true + + + + + + + + + Reverting this setting will slow down initial synchronisation due to validating old transactions + + + Skip validation of the transactions until after block: + + + true + + + + + + + Qt::Horizontal + + + + + + + + + + + Qt::Horizontal + + + + + + + 64 + + + + + + + + diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index 4c24df4445..9e55258ac4 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -169,6 +169,37 @@ Intro::Intro(QWidget *parent, int64_t blockchain_size_gb, int64_t chain_state_si UpdateFreeSpaceLabel(); }); + bool have_user_assumevalid = false; + if (gArgs.IsArgSet("-assumevalid")) { + const auto user_assumevalid = gArgs.GetArg("-assumevalid", /* ignored default; determines return type */ ""); + if (uint256S(user_assumevalid).IsNull()) { + // -assumevalid=0: default checkbox to off, and initialise with chainparams later + ui->assumevalid->setChecked(false); + } else { + // -assumevalid=blockhash: initialise with the user-specified value, enabled + ui->assumevalid->setChecked(true); + ui->assumevalidBlock->setText(QString::fromStdString(user_assumevalid)); + have_user_assumevalid = true; + } + } + if (!have_user_assumevalid) { + const auto chainparams = CreateChainParams(gArgs, gArgs.GetChainType()); + const uint256 default_assumevalid = chainparams ? chainparams->GetConsensus().defaultAssumeValid : uint256(); + if (default_assumevalid.IsNull()) { + // no chainparams assumevalid (nor user-provided), so hide the options entirely + ui->groupAssumeValid->setVisible(false); + } else { + // assumevalid from chainparams only (normal case): disable editing of blockhash + ui->assumevalidBlock->setText(QString::fromStdString(default_assumevalid.GetHex())); + ui->assumevalidBlock->setReadOnly(true); + } + } + { + // TODO: Ideally, we would include actual margins here (instead of extra digits), but this seems non-trivial + const int text_width = ui->assumevalidBlock->fontMetrics().horizontalAdvance(QStringLiteral("4")) * (64 + 4); + ui->assumevalidBlock->setFixedWidth(text_width); + } + startThread(); } @@ -210,9 +241,17 @@ int64_t Intro::getPruneMiB() const } } -bool Intro::showIfNeeded(bool& did_show_intro, int64_t& prune_MiB) +QString Intro::getAssumeValid() const { - did_show_intro = false; + if (!ui->assumevalid->isChecked()) { + return QStringLiteral("0"); + } + return ui->assumevalidBlock->text(); +} + +bool Intro::showIfNeeded(std::unique_ptr& intro) +{ + intro.reset(); QSettings settings; /* If data directory provided on command line, no need to look at settings @@ -234,19 +273,18 @@ bool Intro::showIfNeeded(bool& did_show_intro, int64_t& prune_MiB) } /* If current default data directory does not exist, let the user choose one */ - Intro intro(nullptr, Params().AssumedBlockchainSize(), Params().AssumedChainStateSize()); - intro.setDataDirectory(dataDir); - intro.setWindowIcon(QIcon(":icons/bitcoin")); - did_show_intro = true; + intro = std::make_unique(nullptr, Params().AssumedBlockchainSize(), Params().AssumedChainStateSize()); + intro->setDataDirectory(dataDir); + intro->setWindowIcon(QIcon(QStringLiteral(":icons/bitcoin"))); while(true) { - if(!intro.exec()) + if(!intro->exec()) { /* Cancel clicked */ return false; } - dataDir = intro.getDataDirectory(); + dataDir = intro->getDataDirectory(); try { if (TryCreateDirectories(GUIUtil::QStringToPath(dataDir))) { // If a new data directory has been created, make wallets subdirectory too @@ -260,9 +298,6 @@ bool Intro::showIfNeeded(bool& did_show_intro, int64_t& prune_MiB) } } - // Additional preferences: - prune_MiB = intro.getPruneMiB(); - settings.setValue("strDataDir", dataDir); settings.setValue("fReset", false); } diff --git a/src/qt/intro.h b/src/qt/intro.h index 1a41cb7467..b9cd9353fa 100644 --- a/src/qt/intro.h +++ b/src/qt/intro.h @@ -9,6 +9,8 @@ #include #include +#include + static const bool DEFAULT_CHOOSE_DATADIR = false; class FreespaceChecker; @@ -37,6 +39,7 @@ public: QString getDataDirectory(); void setDataDirectory(const QString &dataDir); int64_t getPruneMiB() const; + QString getAssumeValid() const; /** * Determine data directory. Let the user choose if the current one doesn't exist. @@ -48,7 +51,7 @@ public: * @note do NOT call global gArgs.GetDataDirNet() before calling this function, this * will cause the wrong path to be cached. */ - static bool showIfNeeded(bool& did_show_intro, int64_t& prune_MiB); + static bool showIfNeeded(std::unique_ptr& intro); Q_SIGNALS: void requestCheck();