From a28c48bc4cfcb7fa0535901f84e3c16a07928435 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Thu, 3 Aug 2023 19:22:39 +0000 Subject: [PATCH] Qt/Options: Switch prune setting from GB to MiB --- src/qt/bitcoin.cpp | 2 +- src/qt/forms/intro.ui | 6 ++--- src/qt/forms/optionsdialog.ui | 4 +-- src/qt/guiconstants.h | 5 +++- src/qt/intro.cpp | 29 ++++++++++----------- src/qt/intro.h | 2 +- src/qt/optionsdialog.cpp | 13 +++++----- src/qt/optionsmodel.cpp | 47 ++++++++++++++++------------------- src/qt/optionsmodel.h | 14 ++--------- 9 files changed, 56 insertions(+), 66 deletions(-) diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index 690c2b6f5a..375a2d9fcf 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -340,7 +340,7 @@ void BitcoinApplication::parameterSetup() void BitcoinApplication::InitPruneSetting(int64_t prune_MiB) { - optionsModel->SetPruneTargetGB(PruneMiBtoGB(prune_MiB)); + optionsModel->SetPruneTargetMiB(prune_MiB); } void BitcoinApplication::requestInitialize() diff --git a/src/qt/forms/intro.ui b/src/qt/forms/intro.ui index 074ed42c92..d417f8fa38 100644 --- a/src/qt/forms/intro.ui +++ b/src/qt/forms/intro.ui @@ -243,16 +243,16 @@ - + - GB + MiB - pruneGB + pruneMiB diff --git a/src/qt/forms/optionsdialog.ui b/src/qt/forms/optionsdialog.ui index fd9766f9c9..5576f02f90 100644 --- a/src/qt/forms/optionsdialog.ui +++ b/src/qt/forms/optionsdialog.ui @@ -63,12 +63,12 @@ - + - GB + MiB Qt::PlainText diff --git a/src/qt/guiconstants.h b/src/qt/guiconstants.h index 30ffa302a4..a0467369b3 100644 --- a/src/qt/guiconstants.h +++ b/src/qt/guiconstants.h @@ -54,10 +54,13 @@ static const int TOOLTIP_WRAP_THRESHOLD = 80; #define QAPP_APP_NAME_SIGNET "Bitcoin-Qt-signet" #define QAPP_APP_NAME_REGTEST "Bitcoin-Qt-regtest" +/* One mebibyte (MiB) in bytes */ +static constexpr uint64_t MiB_BYTES{1024 * 1024}; + /* One gigabyte (GB) in bytes */ static constexpr uint64_t GB_BYTES{1000000000}; // Default prune target displayed in GUI. -static constexpr int DEFAULT_PRUNE_TARGET_GB{2}; +static constexpr int DEFAULT_PRUNE_TARGET_MiB{1907}; #endif // BITCOIN_QT_GUICONSTANTS_H diff --git a/src/qt/intro.cpp b/src/qt/intro.cpp index b5cabe06e8..c3d2075901 100644 --- a/src/qt/intro.cpp +++ b/src/qt/intro.cpp @@ -111,11 +111,11 @@ void FreespaceChecker::check() namespace { //! Return pruning size that will be used if automatic pruning is enabled. -int GetPruneTargetGB() +int GetPruneTargetMiB() { int64_t prune_target_mib = gArgs.GetIntArg("-prune", 0); // >1 means automatic pruning is enabled by config, 1 means manual pruning, 0 means no pruning. - return prune_target_mib > 1 ? PruneMiBtoGB(prune_target_mib) : DEFAULT_PRUNE_TARGET_GB; + return prune_target_mib > 1 ? prune_target_mib : DEFAULT_PRUNE_TARGET_MiB; } } // namespace @@ -124,7 +124,7 @@ Intro::Intro(QWidget *parent, int64_t blockchain_size_gb, int64_t chain_state_si ui(new Ui::Intro), m_blockchain_size_gb(blockchain_size_gb), m_chain_state_size_gb(chain_state_size_gb), - m_prune_target_gb{GetPruneTargetGB()} + m_prune_target_mib{GetPruneTargetMiB()} { ui->setupUi(this); ui->welcomeLabel->setText(ui->welcomeLabel->text().arg(PACKAGE_NAME)); @@ -138,15 +138,15 @@ Intro::Intro(QWidget *parent, int64_t blockchain_size_gb, int64_t chain_state_si ); ui->lblExplanation2->setText(ui->lblExplanation2->text().arg(PACKAGE_NAME)); - const int min_prune_target_GB = std::ceil(MIN_DISK_SPACE_FOR_BLOCK_FILES / 1e9); - ui->pruneGB->setRange(min_prune_target_GB, std::numeric_limits::max()); + const int min_prune_target_MiB = (MIN_DISK_SPACE_FOR_BLOCK_FILES + MiB_BYTES - 1) / MiB_BYTES; + ui->pruneMiB->setRange(min_prune_target_MiB, std::numeric_limits::max()); if (gArgs.IsArgSet("-prune")) { m_prune_checkbox_is_default = false; ui->prune->setChecked(gArgs.GetIntArg("-prune", 0) >= 1); ui->prune->setEnabled(false); } - ui->pruneGB->setValue(m_prune_target_gb); - ui->pruneGB->setToolTip(ui->prune->toolTip()); + ui->pruneMiB->setValue(m_prune_target_mib); + ui->pruneMiB->setToolTip(ui->prune->toolTip()); ui->lblPruneSuffix->setToolTip(ui->prune->toolTip()); UpdatePruneLabels(ui->prune->isChecked()); @@ -155,8 +155,8 @@ Intro::Intro(QWidget *parent, int64_t blockchain_size_gb, int64_t chain_state_si UpdatePruneLabels(prune_checked); UpdateFreeSpaceLabel(); }); - connect(ui->pruneGB, qOverload(&QSpinBox::valueChanged), [this](int prune_GB) { - m_prune_target_gb = prune_GB; + connect(ui->pruneMiB, qOverload(&QSpinBox::valueChanged), [this](int prune_MiB) { + m_prune_target_mib = prune_MiB; UpdatePruneLabels(ui->prune->isChecked()); UpdateFreeSpaceLabel(); }); @@ -196,7 +196,7 @@ int64_t Intro::getPruneMiB() const { switch (ui->prune->checkState()) { case Qt::Checked: - return PruneGBtoMiB(m_prune_target_gb); + return m_prune_target_mib; case Qt::Unchecked: default: return 0; } @@ -376,14 +376,15 @@ void Intro::UpdatePruneLabels(bool prune_checked) { m_required_space_gb = m_blockchain_size_gb + m_chain_state_size_gb; QString storageRequiresMsg = tr("At least %1 GB of data will be stored in this directory, and it will grow over time."); - if (prune_checked && m_prune_target_gb <= m_blockchain_size_gb) { - m_required_space_gb = m_prune_target_gb + m_chain_state_size_gb; + const int64_t prune_target_gb = (m_prune_target_mib * MiB_BYTES + GB_BYTES - 1) / GB_BYTES; + if (prune_checked && prune_target_gb <= m_blockchain_size_gb) { + m_required_space_gb = prune_target_gb + m_chain_state_size_gb; storageRequiresMsg = tr("Approximately %1 GB of data will be stored in this directory."); } - ui->pruneGB->setEnabled(prune_checked); + ui->pruneMiB->setEnabled(prune_checked); static constexpr uint64_t nPowTargetSpacing = 10 * 60; // from chainparams, which we don't have at this stage static constexpr uint32_t expected_block_data_size = 2250000; // includes undo data - const uint64_t expected_backup_days = m_prune_target_gb * 1e9 / (uint64_t(expected_block_data_size) * 86400 / nPowTargetSpacing); + const uint64_t expected_backup_days = m_prune_target_mib * MiB_BYTES / (uint64_t(expected_block_data_size) * 86400 / nPowTargetSpacing); ui->lblPruneSuffix->setText( //: Explanatory text on the capability of the current prune target. tr("(sufficient to restore backups %n day(s) old)", "", expected_backup_days)); diff --git a/src/qt/intro.h b/src/qt/intro.h index 7b34c73b02..c3f80fd007 100644 --- a/src/qt/intro.h +++ b/src/qt/intro.h @@ -74,7 +74,7 @@ private: //! Total required space (in GB) depending on user choice (prune or not prune). int64_t m_required_space_gb{0}; uint64_t m_bytes_available{0}; - int64_t m_prune_target_gb; + int64_t m_prune_target_mib; void startThread(); void checkPath(const QString &dataDir); diff --git a/src/qt/optionsdialog.cpp b/src/qt/optionsdialog.cpp index 98b2489f19..64f398bd0b 100644 --- a/src/qt/optionsdialog.cpp +++ b/src/qt/optionsdialog.cpp @@ -102,8 +102,8 @@ OptionsDialog::OptionsDialog(QWidget* parent, bool enableWallet) ui->pruneWarning->setVisible(false); ui->pruneWarning->setStyleSheet("QLabel { color: red; }"); - ui->pruneSize->setEnabled(false); - connect(ui->prune, &QPushButton::toggled, ui->pruneSize, &QWidget::setEnabled); + ui->pruneSizeMiB->setEnabled(false); + connect(ui->prune, &QPushButton::toggled, ui->pruneSizeMiB, &QWidget::setEnabled); ui->networkPort->setValidator(new QIntValidator(1024, 65535, this)); connect(ui->networkPort, SIGNAL(textChanged(const QString&)), this, SLOT(checkLineEdit())); @@ -243,9 +243,8 @@ void OptionsDialog::setModel(OptionsModel *_model) if (_model->isRestartRequired()) showRestartWarning(true); - // Prune values are in GB to be consistent with intro.cpp - static constexpr uint64_t nMinDiskSpace = (MIN_DISK_SPACE_FOR_BLOCK_FILES / GB_BYTES) + (MIN_DISK_SPACE_FOR_BLOCK_FILES % GB_BYTES) ? 1 : 0; - ui->pruneSize->setRange(nMinDiskSpace, std::numeric_limits::max()); + static constexpr uint64_t nMinDiskSpace = (MIN_DISK_SPACE_FOR_BLOCK_FILES + MiB_BYTES - 1) / MiB_BYTES; + ui->pruneSizeMiB->setRange(nMinDiskSpace, std::numeric_limits::max()); QString strLabel = _model->getOverriddenByCommandLine(); if (strLabel.isEmpty()) @@ -270,7 +269,7 @@ void OptionsDialog::setModel(OptionsModel *_model) /* Main */ connect(ui->prune, &QCheckBox::clicked, this, &OptionsDialog::showRestartWarning); connect(ui->prune, &QCheckBox::clicked, this, &OptionsDialog::togglePruneWarning); - connect(ui->pruneSize, qOverload(&QSpinBox::valueChanged), this, &OptionsDialog::showRestartWarning); + connect(ui->pruneSizeMiB, qOverload(&QSpinBox::valueChanged), this, &OptionsDialog::showRestartWarning); connect(ui->databaseCache, qOverload(&QSpinBox::valueChanged), this, &OptionsDialog::showRestartWarning); connect(ui->externalSignerPath, &QLineEdit::textChanged, [this]{ showRestartWarning(); }); connect(ui->threadsScriptVerif, qOverload(&QSpinBox::valueChanged), this, &OptionsDialog::showRestartWarning); @@ -305,7 +304,7 @@ void OptionsDialog::setMapper() mapper->addMapping(ui->threadsScriptVerif, OptionsModel::ThreadsScriptVerif); mapper->addMapping(ui->databaseCache, OptionsModel::DatabaseCache); mapper->addMapping(ui->prune, OptionsModel::Prune); - mapper->addMapping(ui->pruneSize, OptionsModel::PruneSize); + mapper->addMapping(ui->pruneSizeMiB, OptionsModel::PruneSizeMiB); /* Wallet */ mapper->addMapping(ui->spendZeroConfChange, OptionsModel::SpendZeroConfChange); diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 1ca95dd414..9829092217 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -53,7 +53,7 @@ static const char* SettingName(OptionsModel::OptionID option) case OptionsModel::MapPortNatpmp: return "natpmp"; case OptionsModel::Listen: return "listen"; case OptionsModel::Server: return "server"; - case OptionsModel::PruneSize: return "prune"; + case OptionsModel::PruneSizeMiB: return "prune"; case OptionsModel::Prune: return "prune"; case OptionsModel::ProxyIP: return "proxy"; case OptionsModel::ProxyPort: return "proxy"; @@ -73,7 +73,7 @@ static void UpdateRwSetting(interfaces::Node& node, OptionsModel::OptionID optio (option == OptionsModel::DatabaseCache || option == OptionsModel::ThreadsScriptVerif || option == OptionsModel::Prune || - option == OptionsModel::PruneSize)) { + option == OptionsModel::PruneSizeMiB)) { // Write certain old settings as strings, even though they are numbers, // because Bitcoin 22.x releases try to read these specific settings as // strings in addOverriddenOption() calls at startup, triggering @@ -88,10 +88,10 @@ static void UpdateRwSetting(interfaces::Node& node, OptionsModel::OptionID optio } //! Convert enabled/size values to bitcoin -prune setting. -static common::SettingsValue PruneSetting(bool prune_enabled, int prune_size_gb) +static common::SettingsValue PruneSettingFromMiB(bool prune_enabled, int prune_size_mib) { - assert(!prune_enabled || prune_size_gb >= 1); // PruneSizeGB and ParsePruneSizeGB never return less - return prune_enabled ? PruneGBtoMiB(prune_size_gb) : 0; + assert(!prune_enabled || prune_size_mib >= 1); // PruneSizeMiB and ParsePruneSizeMiB never return less + return prune_enabled ? prune_size_mib : 0; } //! Get pruning enabled value to show in GUI from bitcoin -prune setting. @@ -103,18 +103,10 @@ static bool PruneEnabled(const common::SettingsValue& prune_setting) //! Get pruning size value to show in GUI from bitcoin -prune setting. If //! pruning is not enabled, just show default recommended pruning size (2GB). -static int PruneSizeGB(const common::SettingsValue& prune_setting) +static int PruneSizeAsMiB(const common::SettingsValue& prune_setting) { int value = SettingToInt(prune_setting, 0); - return value > 1 ? PruneMiBtoGB(value) : DEFAULT_PRUNE_TARGET_GB; -} - -//! Parse pruning size value provided by user in GUI or loaded from QSettings -//! (windows registry key or qt .conf file). Smallest value that the GUI can -//! display is 1 GB, so round up if anything less is parsed. -static int ParsePruneSizeGB(const QVariant& prune_size) -{ - return std::max(1, prune_size.toInt()); + return value > 1 ? value : DEFAULT_PRUNE_TARGET_MiB; } struct ProxySetting { @@ -375,10 +367,10 @@ static QString GetDefaultProxyAddress() return QString("%1:%2").arg(DEFAULT_GUI_PROXY_HOST).arg(DEFAULT_GUI_PROXY_PORT); } -void OptionsModel::SetPruneTargetGB(int prune_target_gb) +void OptionsModel::SetPruneTargetMiB(int prune_target_mib) { const common::SettingsValue cur_value = node().getPersistentSetting("prune"); - const common::SettingsValue new_value = PruneSetting(prune_target_gb > 0, prune_target_gb); + const common::SettingsValue new_value = PruneSettingFromMiB(prune_target_mib > 0, prune_target_mib); // Force setting to take effect. It is still safe to change the value at // this point because this function is only called after the intro screen is @@ -389,7 +381,7 @@ void OptionsModel::SetPruneTargetGB(int prune_target_gb) // from saved value. Avoid writing settings.json if bitcoin.conf value // doesn't need to be overridden. if (PruneEnabled(cur_value) != PruneEnabled(new_value) || - PruneSizeGB(cur_value) != PruneSizeGB(new_value)) { + PruneSizeAsMiB(cur_value) != PruneSizeAsMiB(new_value)) { // Call UpdateRwSetting() instead of setOption() to avoid setting // RestartRequired flag UpdateRwSetting(node(), Prune, "", new_value); @@ -513,10 +505,10 @@ QVariant OptionsModel::getOption(OptionID option, const std::string& suffix) con return settings.value("enable_psbt_controls"); case Prune: return PruneEnabled(setting()); - case PruneSize: - return PruneEnabled(setting()) ? PruneSizeGB(setting()) : + case PruneSizeMiB: + return PruneEnabled(setting()) ? PruneSizeAsMiB(setting()) : suffix.empty() ? getOption(option, "-prev") : - DEFAULT_PRUNE_TARGET_GB; + DEFAULT_PRUNE_TARGET_MiB; case DatabaseCache: return qlonglong(SettingToInt(setting(), nDefaultDbCache)); case ThreadsScriptVerif: @@ -753,17 +745,17 @@ bool OptionsModel::setOption(OptionID option, const QVariant& value, const std:: case Prune: if (changed()) { if (suffix.empty() && !value.toBool()) setOption(option, true, "-prev"); - update(PruneSetting(value.toBool(), getOption(PruneSize).toInt())); + update(PruneSettingFromMiB(value.toBool(), getOption(PruneSizeMiB).toInt())); if (suffix.empty() && value.toBool()) UpdateRwSetting(node(), option, "-prev", {}); if (suffix.empty()) setRestartRequired(true); } break; - case PruneSize: + case PruneSizeMiB: if (changed()) { if (suffix.empty() && !getOption(Prune).toBool()) { setOption(option, value, "-prev"); } else { - update(PruneSetting(true, ParsePruneSizeGB(value))); + update(PruneSettingFromMiB(true, value.toInt())); } if (suffix.empty() && getOption(Prune).toBool()) setRestartRequired(true); } @@ -882,6 +874,11 @@ void OptionsModel::checkAndMigrate() ProxySetting parsed = ParseProxyString(value.toString()); setOption(ProxyIPTor, parsed.ip); setOption(ProxyPortTor, parsed.port); + } else if (option == PruneSizeMiB) { + // Stored as GB + const int64_t prune_size_gb = value.toInt(); + const int prune_size_mib = std::max(prune_size_gb * GB_BYTES / MiB_BYTES, MIN_DISK_SPACE_FOR_BLOCK_FILES / MiB_BYTES); + setOption(option, prune_size_mib); } else { setOption(option, value); } @@ -899,7 +896,7 @@ void OptionsModel::checkAndMigrate() migrate_setting(MapPortNatpmp, "fUseNatpmp"); migrate_setting(Listen, "fListen"); migrate_setting(Server, "server"); - migrate_setting(PruneSize, "nPruneSize"); + migrate_setting(PruneSizeMiB, "nPruneSize"); migrate_setting(Prune, "bPrune"); migrate_setting(ProxyIP, "addrProxy"); migrate_setting(ProxyUse, "fUseProxy"); diff --git a/src/qt/optionsmodel.h b/src/qt/optionsmodel.h index 0853c0de40..7d3c1eaa41 100644 --- a/src/qt/optionsmodel.h +++ b/src/qt/optionsmodel.h @@ -23,16 +23,6 @@ class Node; extern const char *DEFAULT_GUI_PROXY_HOST; static constexpr uint16_t DEFAULT_GUI_PROXY_PORT = 9050; -/** - * Convert configured prune target MiB to displayed GB. Round up to avoid underestimating max disk usage. - */ -static inline int PruneMiBtoGB(int64_t mib) { return (mib * 1024 * 1024 + GB_BYTES - 1) / GB_BYTES; } - -/** - * Convert displayed prune target GB to configured MiB. Round down so roundtrip GB -> MiB -> GB conversion is stable. - */ -static inline int64_t PruneGBtoMiB(int gb) { return gb * GB_BYTES / 1024 / 1024; } - /** Interface from Qt to configuration data structure for Bitcoin client. To Qt, the options are presented as a list with the different options laid out vertically. @@ -70,7 +60,7 @@ public: SubFeeFromAmount, // bool ThreadsScriptVerif, // int Prune, // bool - PruneSize, // int + PruneSizeMiB, // int DatabaseCache, // int ExternalSignerPath, // QString SpendZeroConfChange, // bool @@ -121,7 +111,7 @@ public: bool hasSigner(); /* Explicit setters */ - void SetPruneTargetGB(int prune_target_gb); + void SetPruneTargetMiB(int prune_target_mib); /* Restart flag helper */ void setRestartRequired(bool fRequired);