From ce2f3321140884c04fd94f3ce87d2ef97ff6a206 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Thu, 27 Mar 2025 09:17:38 +0100 Subject: [PATCH] subaddress: cleanup --- src/MainWindow.cpp | 5 +- src/ReceiveWidget.cpp | 2 +- src/dialog/AccountSwitcherDialog.cpp | 7 ++- src/libwalletqt/Subaddress.cpp | 94 ++++++++++++++++------------ src/libwalletqt/Subaddress.h | 10 ++- src/libwalletqt/Wallet.cpp | 16 ++--- src/libwalletqt/Wallet.h | 2 - src/libwalletqt/rows/SubaddressRow.h | 6 +- src/model/SubaddressModel.cpp | 13 ++-- src/model/SubaddressModel.h | 3 +- 10 files changed, 85 insertions(+), 73 deletions(-) diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 2e0f89c7..656e24e8 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -572,13 +572,12 @@ void MainWindow::onWalletOpened() { this->setEnabled(true); // receive page - m_wallet->subaddress()->refresh(m_wallet->currentSubaddressAccount()); + m_wallet->subaddress()->refresh(); if (m_wallet->subaddress()->count() == 1) { for (int i = 0; i < 10; i++) { - m_wallet->subaddress()->addRow(m_wallet->currentSubaddressAccount(), ""); + m_wallet->subaddress()->addRow(""); } } - m_wallet->subaddressModel()->setCurrentSubaddressAccount(m_wallet->currentSubaddressAccount()); // history page m_wallet->history()->refresh(); diff --git a/src/ReceiveWidget.cpp b/src/ReceiveWidget.cpp index 99d9ae26..01219c0e 100644 --- a/src/ReceiveWidget.cpp +++ b/src/ReceiveWidget.cpp @@ -236,7 +236,7 @@ void ReceiveWidget::showOnDevice() { } void ReceiveWidget::generateSubaddress() { - bool r = m_wallet->subaddress()->addRow(m_wallet->currentSubaddressAccount(), ""); + bool r = m_wallet->subaddress()->addRow(""); if (!r) { Utils::showError(this, "Failed to generate subaddress", m_wallet->subaddress()->getError()); } diff --git a/src/dialog/AccountSwitcherDialog.cpp b/src/dialog/AccountSwitcherDialog.cpp index 15028dd7..557b59ed 100644 --- a/src/dialog/AccountSwitcherDialog.cpp +++ b/src/dialog/AccountSwitcherDialog.cpp @@ -43,8 +43,11 @@ AccountSwitcherDialog::AccountSwitcherDialog(Wallet *wallet, QWidget *parent) connect(ui->accounts, &QTreeView::customContextMenuRequested, this, &AccountSwitcherDialog::showContextMenu); connect(ui->btn_newAccount, &QPushButton::clicked, [this]{ - m_wallet->addSubaddressAccount("New account"); - m_wallet->subaddressAccount()->refresh(); + m_wallet->addSubaddressAccount("New account"); + m_wallet->subaddressAccount()->refresh(); + for (int i = 0; i < 10; i ++) { + m_wallet->subaddress()->addRow(""); + } }); connect(m_wallet->subaddressAccount(), &SubaddressAccount::refreshFinished, this, &AccountSwitcherDialog::updateSelection); diff --git a/src/libwalletqt/Subaddress.cpp b/src/libwalletqt/Subaddress.cpp index b7e2ecc2..56d368b2 100644 --- a/src/libwalletqt/Subaddress.cpp +++ b/src/libwalletqt/Subaddress.cpp @@ -18,50 +18,26 @@ Subaddress::Subaddress(Wallet *wallet, tools::wallet2 *wallet2, QObject *parent) m_hidden = hidden.split(","); connect(this, &Subaddress::noUnusedSubaddresses, [this] { - this->addRow(m_wallet->currentSubaddressAccount(), ""); + this->addRow(""); }); } -bool Subaddress::refresh(quint32 accountIndex) +bool Subaddress::refresh() { emit refreshStarted(); m_rows.clear(); - bool haveUnused = false; bool potentialWalletFileCorruption = false; + quint32 accountIndex = m_wallet->currentSubaddressAccount(); for (quint32 i = 0; i < m_wallet2->get_num_subaddresses(accountIndex); ++i) { - cryptonote::subaddress_index index = {accountIndex, i}; - cryptonote::account_public_address address = m_wallet2->get_subaddress(index); - - // Make sure we have previously generated Di - auto idx = m_wallet2->get_subaddress_index(address); - if (!idx) { - potentialWalletFileCorruption = true; - break; - } - - // Verify mapping - if (idx != index) { + bool r = emplaceRow(i); + if (!r) { potentialWalletFileCorruption = true; break; } - - QString addressStr = QString::fromStdString(cryptonote::get_account_address_as_str(m_wallet2->nettype(), !index.is_zero(), address)); - - bool used = m_wallet2->get_subaddress_used({accountIndex, (uint32_t)i}); - m_rows.emplace_back( - addressStr, - QString::fromStdString(m_wallet2->get_subaddress_label(index)), - used, - this->isHidden(addressStr), - this->isPinned(addressStr) - ); - if (!used && i > 0) { - haveUnused = true; - } } // Make sure keys are intact. We NEVER want to display incorrect addresses in case of memory corruption. @@ -75,10 +51,6 @@ bool Subaddress::refresh(quint32 accountIndex) emit refreshFinished(); - if (!haveUnused) { - emit noUnusedSubaddresses(); - } - return !potentialWalletFileCorruption; } @@ -125,14 +97,52 @@ const QList& Subaddress::getRows() return m_rows; } -bool Subaddress::addRow(quint32 accountIndex, const QString &label) +bool Subaddress::emplaceRow(quint32 addressIndex) +{ + cryptonote::subaddress_index index = {m_wallet->currentSubaddressAccount(), addressIndex}; + cryptonote::account_public_address address = m_wallet2->get_subaddress(index); + + // Make sure we have previously generated Di + auto idx = m_wallet2->get_subaddress_index(address); + if (!idx) { + return false; + } + + // Verify mapping + if (idx != index) { + return false; + } + + if (m_rows.length() != addressIndex) { + return false; + } + + QString addressStr = QString::fromStdString(cryptonote::get_account_address_as_str(m_wallet2->nettype(), !index.is_zero(), address)); + + bool used = m_wallet2->get_subaddress_used(index); + m_rows.emplace_back( + addressStr, + QString::fromStdString(m_wallet2->get_subaddress_label(index)), + used, + this->isHidden(addressStr), + this->isPinned(addressStr), + index.is_zero() + ); + return true; +} + +bool Subaddress::addRow(const QString &label) { // This can fail if hardware device is unplugged during operating, catch here to prevent crash // Todo: Notify GUI that it was a device error try { - m_wallet2->add_subaddress(accountIndex, label.toStdString()); - refresh(accountIndex); + quint32 addressIndex = m_wallet->numSubaddresses(m_wallet->currentSubaddressAccount()); + m_wallet2->add_subaddress(m_wallet->currentSubaddressAccount(), label.toStdString()); + + emit beginAddRow(addressIndex); + emplaceRow(addressIndex); + emit endAddRow(); } catch (const std::exception& e) { @@ -145,11 +155,13 @@ bool Subaddress::addRow(quint32 accountIndex, const QString &label) return true; } -bool Subaddress::setLabel(quint32 accountIndex, quint32 addressIndex, const QString &label) +bool Subaddress::setLabel(quint32 addressIndex, const QString &label) { try { - m_wallet2->set_subaddress_label({accountIndex, addressIndex}, label.toStdString()); - refresh(accountIndex); + m_wallet2->set_subaddress_label({m_wallet->currentSubaddressAccount(), addressIndex}, label.toStdString()); + SubaddressRow& row = m_rows[addressIndex]; + row.label = label; + emit rowUpdated(addressIndex); } catch (const std::exception& e) { @@ -176,7 +188,7 @@ bool Subaddress::setHidden(const QString &address, bool hidden) bool r = m_wallet->setCacheAttribute("feather.hiddenaddresses", m_hidden.join(",")); - refresh(m_wallet->currentSubaddressAccount()); + refresh(); return r; } @@ -197,7 +209,7 @@ bool Subaddress::setPinned(const QString &address, bool pinned) bool r = m_wallet->setCacheAttribute("feather.pinnedaddresses", m_pinned.join(",")); - refresh(m_wallet->currentSubaddressAccount()); + refresh(); return r; } diff --git a/src/libwalletqt/Subaddress.h b/src/libwalletqt/Subaddress.h index 03c0931f..b9da8473 100644 --- a/src/libwalletqt/Subaddress.h +++ b/src/libwalletqt/Subaddress.h @@ -19,7 +19,7 @@ class Subaddress : public QObject Q_OBJECT public: - bool refresh(quint32 accountIndex); + bool refresh(); void updateUsed(quint32 accountIndex); [[nodiscard]] qsizetype count() const; @@ -27,8 +27,8 @@ public: const SubaddressRow& getRow(qsizetype i); const QList& getRows(); - bool addRow(quint32 accountIndex, const QString &label); - bool setLabel(quint32 accountIndex, quint32 addressIndex, const QString &label); + bool addRow(const QString &label); + bool setLabel(quint32 addressIndex, const QString &label); bool setHidden(const QString& address, bool hidden); bool setPinned(const QString& address, bool pinned); bool isHidden(const QString& address); @@ -42,8 +42,12 @@ signals: void rowUpdated(qsizetype index) const; void corrupted() const; void noUnusedSubaddresses() const; + void beginAddRow(qsizetype index) const; + void endAddRow() const; private: + bool emplaceRow(quint32 addressIndex); + explicit Subaddress(Wallet *wallet, tools::wallet2 *wallet2, QObject *parent); friend class Wallet; diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp index f71ade59..fb693f0c 100644 --- a/src/libwalletqt/Wallet.cpp +++ b/src/libwalletqt/Wallet.cpp @@ -295,10 +295,9 @@ void Wallet::switchSubaddressAccount(quint32 accountIndex) { { qWarning() << "failed to set " << ATTRIBUTE_SUBADDRESS_ACCOUNT << " cache attribute"; } - m_subaddress->refresh(m_currentSubaddressAccount); + m_subaddress->refresh(); m_history->refresh(); m_coins->refresh(); - this->subaddressModel()->setCurrentSubaddressAccount(m_currentSubaddressAccount); this->coinsModel()->setCurrentSubaddressAccount(m_currentSubaddressAccount); this->updateBalance(); this->setSelectedInputs({}); @@ -318,18 +317,10 @@ quint32 Wallet::numSubaddresses(quint32 accountIndex) const { return m_wallet2->get_num_subaddresses(accountIndex); } -void Wallet::addSubaddress(const QString& label) { - m_wallet2->add_subaddress(currentSubaddressAccount(), label.toStdString()); -} - QString Wallet::getSubaddressLabel(quint32 accountIndex, quint32 addressIndex) const { return QString::fromStdString(m_walletImpl->getSubaddressLabel(accountIndex, addressIndex)); } -void Wallet::setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, const QString &label) { - m_walletImpl->setSubaddressLabel(accountIndex, addressIndex, label.toStdString()); -} - void Wallet::deviceShowAddressAsync(quint32 accountIndex, quint32 addressIndex, const QString &paymentId) { m_scheduler.run([this, accountIndex, addressIndex, paymentId] { m_walletImpl->deviceShowAddress(accountIndex, addressIndex, paymentId.toStdString()); @@ -440,6 +431,7 @@ void Wallet::initAsync(const QString &daemonAddress, bool trustedDaemon, quint64 // #################### Synchronization (Refresh) #################### void Wallet::startRefresh() { + m_refreshEnabled = true; m_refreshEnabled = true; m_refreshNow = true; } @@ -599,7 +591,7 @@ void Wallet::onRefreshed(bool success, const QString &message) { void Wallet::refreshModels() { m_history->refresh(); m_coins->refresh(); - this->subaddress()->refresh(this->currentSubaddressAccount()); + m_subaddress->refresh(); } // #################### Hardware wallet #################### @@ -1008,7 +1000,7 @@ void Wallet::onTransactionCommitted(bool success, PendingTransaction *tx, const this->history()->refresh(); this->coins()->refresh(); - this->subaddress()->refresh(this->currentSubaddressAccount()); + this->subaddress()->refresh(); this->updateBalance(); diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h index 79b1f156..2a658f14 100644 --- a/src/libwalletqt/Wallet.h +++ b/src/libwalletqt/Wallet.h @@ -170,9 +170,7 @@ public: void addSubaddressAccount(const QString& label); quint32 numSubaddressAccounts() const; quint32 numSubaddresses(quint32 accountIndex) const; - void addSubaddress(const QString& label); QString getSubaddressLabel(quint32 accountIndex, quint32 addressIndex) const; - void setSubaddressLabel(quint32 accountIndex, quint32 addressIndex, const QString &label); void deviceShowAddressAsync(quint32 accountIndex, quint32 addressIndex, const QString &paymentId); QString getSubaddressLookahead() const; diff --git a/src/libwalletqt/rows/SubaddressRow.h b/src/libwalletqt/rows/SubaddressRow.h index 3669507f..8bf1b2ed 100644 --- a/src/libwalletqt/rows/SubaddressRow.h +++ b/src/libwalletqt/rows/SubaddressRow.h @@ -13,13 +13,15 @@ struct SubaddressRow bool used = false; bool hidden = false; bool pinned = false; + bool primary = false; - SubaddressRow(const QString& address, const QString &label, bool used, bool hidden, bool pinned) + SubaddressRow(const QString& address, const QString &label, bool used, bool hidden, bool pinned, bool primary) : address(address) , label(label) , used(used) , hidden(hidden) - , pinned(pinned) {} + , pinned(pinned) + , primary(primary) {} }; #endif //FEATHER_SUBADDRESSROW_H diff --git a/src/model/SubaddressModel.cpp b/src/model/SubaddressModel.cpp index b67226cb..7c89d536 100644 --- a/src/model/SubaddressModel.cpp +++ b/src/model/SubaddressModel.cpp @@ -19,6 +19,8 @@ SubaddressModel::SubaddressModel(QObject *parent, Subaddress *subaddress) { connect(m_subaddress, &Subaddress::refreshStarted, this, &SubaddressModel::beginResetModel); connect(m_subaddress, &Subaddress::refreshFinished, this, &SubaddressModel::endResetModel); + connect(m_subaddress, &Subaddress::beginAddRow, this, &SubaddressModel::beginRowAdded); + connect(m_subaddress, &Subaddress::endAddRow, this, &SubaddressModel::endInsertRows); connect(m_subaddress, &Subaddress::rowUpdated, this, &SubaddressModel::rowUpdated); } @@ -163,7 +165,7 @@ bool SubaddressModel::setData(const QModelIndex &index, const QVariant &value, i switch (index.column()) { case Label: - m_subaddress->setLabel(m_currentSubaddressAccount, row, value.toString()); + m_subaddress->setLabel(row, value.toString()); break; default: return false; @@ -186,10 +188,6 @@ Qt::ItemFlags SubaddressModel::flags(const QModelIndex &index) const return QAbstractTableModel::flags(index); } -void SubaddressModel::setCurrentSubaddressAccount(quint32 accountIndex) { - m_currentSubaddressAccount = accountIndex; -} - const SubaddressRow& SubaddressModel::entryFromIndex(const QModelIndex &index) const { Q_ASSERT(index.isValid() && index.row() < m_subaddress->count()); return m_subaddress->row(index.row()); @@ -199,3 +197,8 @@ void SubaddressModel::rowUpdated(qsizetype index) { emit dataChanged(this->index(index, 0), this->index(index, SubaddressModel::COUNT - 1), {Qt::DisplayRole, Qt::EditRole}); } + +void SubaddressModel::beginRowAdded(qsizetype index) +{ + this->beginInsertRows(this->index(index, 0), index, index); +} diff --git a/src/model/SubaddressModel.h b/src/model/SubaddressModel.h index de6abed6..31a1d174 100644 --- a/src/model/SubaddressModel.h +++ b/src/model/SubaddressModel.h @@ -36,9 +36,8 @@ public: const SubaddressRow& entryFromIndex(const QModelIndex &index) const; - void setCurrentSubaddressAccount(quint32 accountIndex); - void rowUpdated(qsizetype index); + void beginRowAdded(qsizetype index); private: Subaddress *m_subaddress; -- 2.52.0