diff --git a/configure.ac b/configure.ac index 53d1a89..00e51fe 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ AC_PREREQ([2.69]) define(_CLIENT_VERSION_MAJOR, 0) define(_CLIENT_VERSION_MINOR, 2) -define(_CLIENT_VERSION_BUILD, 0) +define(_CLIENT_VERSION_BUILD, 1) define(_CLIENT_VERSION_RC, 1) define(_CLIENT_VERSION_IS_RELEASE, true) define(_COPYRIGHT_YEAR, 2026) diff --git a/src/interfaces/wallet.h b/src/interfaces/wallet.h index f507047..16743e6 100644 --- a/src/interfaces/wallet.h +++ b/src/interfaces/wallet.h @@ -262,6 +262,9 @@ public: // Get default address type. virtual OutputType getDefaultAddressType() = 0; + //! Return whether post-quantum consensus rules are active. + virtual bool isPostQuantumActive() = 0; + //! Get max tx fee. virtual CAmount getDefaultMaxTxFee() = 0; diff --git a/src/qt/forms/receivecoinsdialog.ui b/src/qt/forms/receivecoinsdialog.ui index 671f399..7eae10a 100644 --- a/src/qt/forms/receivecoinsdialog.ui +++ b/src/qt/forms/receivecoinsdialog.ui @@ -195,28 +195,25 @@ - - - - 0 - 0 - - - - - 1000 - 16777215 - - - - Qt::StrongFocus - + - Native segwit addresses (aka Bech32 or BIP-173) reduce your transaction fees later on and offer better protection against typos, but old wallets don't support them. When unchecked, an address compatible with older wallets will be created instead. - - - Generate native segwit (Bech32) address + Select the type of receiving address to generate. + + + Standard (vtx1q...) + + + + + ML-DSA (vtx1z...) + + + + + SLH-DSA (vtx1r...) + + @@ -366,7 +363,7 @@ reqLabel reqAmount - useBech32 + addressType reqMessage receiveButton clearButton diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index c55136c..be65143 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -21,6 +22,7 @@ #include #include #include +#include #include ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) : @@ -88,11 +90,15 @@ void ReceiveCoinsDialog::setModel(WalletModel *_model) &QItemSelectionModel::selectionChanged, this, &ReceiveCoinsDialog::recentRequestsView_selectionChanged); - if (model->wallet().getDefaultAddressType() == OutputType::BECH32) { - ui->useBech32->setCheckState(Qt::Checked); - } else { - ui->useBech32->setCheckState(Qt::Unchecked); - } + // Standard SegWit is the default receiving address type. + ui->addressType->setCurrentIndex(0); + updateAddressTypeAvailability(); + + connect(&model->clientModel(), &ClientModel::numBlocksChanged, + this, + [this](int, const QDateTime&, double, bool, SynchronizationState) { + updateAddressTypeAvailability(); + }); // Set the button to be enabled or disabled based on whether the wallet can give out new addresses. ui->receiveButton->setEnabled(model->wallet().canGetAddresses()); @@ -137,6 +143,35 @@ void ReceiveCoinsDialog::updateDisplayUnit() } } +void ReceiveCoinsDialog::updateAddressTypeAvailability() +{ + if (!model) { + return; + } + + const bool pq_active = model->wallet().isPostQuantumActive(); + + auto* item_model = qobject_cast(ui->addressType->model()); + if (!item_model) { + return; + } + + for (int row : {1, 2}) { + if (auto* item = item_model->item(row)) { + item->setEnabled(pq_active); + } + } + + if (!pq_active && ui->addressType->currentIndex() != 0) { + ui->addressType->setCurrentIndex(0); + } + + ui->addressType->setToolTip( + pq_active + ? tr("Select the type of receiving address to generate.") + : tr("Quantum-resistant address types become available when PQR activates at block 6000.")); +} + void ReceiveCoinsDialog::on_receiveButton_clicked() { if(!model || !model->getOptionsModel() || !model->getAddressTableModel() || !model->getRecentRequestsTableModel()) @@ -145,14 +180,31 @@ void ReceiveCoinsDialog::on_receiveButton_clicked() QString address; QString label = ui->reqLabel->text(); /* Generate new receiving address */ - OutputType address_type; - if (ui->useBech32->isChecked()) { + const int address_type_index = ui->addressType->currentIndex(); + + if ((address_type_index == 1 || address_type_index == 2) && + !model->wallet().isPostQuantumActive()) { + QMessageBox::warning( + this, + windowTitle(), + tr("Quantum-resistant addresses will become available when PQR activates at block 6000."), + QMessageBox::Ok, + QMessageBox::Ok); + return; + } + + OutputType address_type = OutputType::BECH32; + switch (address_type_index) { + case 1: + address_type = OutputType::MLDSA; + break; + case 2: + address_type = OutputType::SLHDSA; + break; + case 0: + default: address_type = OutputType::BECH32; - } else { - address_type = model->wallet().getDefaultAddressType(); - if (address_type == OutputType::BECH32) { - address_type = OutputType::P2SH_SEGWIT; - } + break; } address = model->getAddressTableModel()->addRow(AddressTableModel::Receive, label, "", address_type); diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h index 8f90893..6786ed6 100644 --- a/src/qt/receivecoinsdialog.h +++ b/src/qt/receivecoinsdialog.h @@ -51,6 +51,8 @@ public Q_SLOTS: void accept() override; private: + void updateAddressTypeAvailability(); + Ui::ReceiveCoinsDialog *ui; WalletModel *model; QMenu *contextMenu; diff --git a/src/wallet/interfaces.cpp b/src/wallet/interfaces.cpp index 497912d..19292d5 100644 --- a/src/wallet/interfaces.cpp +++ b/src/wallet/interfaces.cpp @@ -454,6 +454,10 @@ public: bool hasExternalSigner() override { return m_wallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER); } bool privateKeysDisabled() override { return m_wallet->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS); } OutputType getDefaultAddressType() override { return m_wallet->m_default_address_type; } + bool isPostQuantumActive() override + { + return m_wallet->chain().isDeploymentActive(Consensus::DEPLOYMENT_PQR); + } CAmount getDefaultMaxTxFee() override { return m_wallet->m_default_max_tx_fee; } void remove() override {