From 3603e5e8bafedc3c88b2f173c328571f9c4e44bf Mon Sep 17 00:00:00 2001 From: levonpetrosyan93 Date: Sat, 10 Aug 2024 16:55:40 +0400 Subject: [PATCH 1/7] Lelantus UI stripped --- src/Makefile.qt.include | 19 +- src/qt/automintdialog.cpp | 143 --- src/qt/automintdialog.h | 40 - src/qt/automintmodel.cpp | 186 --- src/qt/automintmodel.h | 64 - src/qt/automintnotification.cpp | 53 - src/qt/automintnotification.h | 26 - src/qt/bitcoingui.cpp | 42 - src/qt/bitcoingui.h | 8 +- src/qt/forms/lelantusdialog.ui | 1644 -------------------------- src/qt/forms/sendtopcodedialog.ui | 277 ----- src/qt/lelantuscoincontroldialog.cpp | 770 ------------ src/qt/lelantuscoincontroldialog.h | 114 -- src/qt/lelantusdialog.cpp | 763 ------------ src/qt/lelantusdialog.h | 105 -- src/qt/lelantusmodel.cpp | 129 -- src/qt/lelantusmodel.h | 56 - src/qt/overviewpage.cpp | 22 +- src/qt/pcodemodel.cpp | 257 ---- src/qt/pcodemodel.h | 63 - src/qt/sendcoinsdialog.cpp | 52 +- src/qt/sendtopcodedialog.cpp | 329 ------ src/qt/sendtopcodedialog.h | 90 -- src/qt/transactionview.cpp | 20 - src/qt/transactionview.h | 2 - src/qt/walletframe.cpp | 7 - src/qt/walletframe.h | 2 - src/qt/walletmodel.cpp | 307 +---- src/qt/walletmodel.h | 29 +- src/qt/walletview.cpp | 124 +- src/qt/walletview.h | 18 - 31 files changed, 25 insertions(+), 5736 deletions(-) delete mode 100644 src/qt/forms/lelantusdialog.ui delete mode 100644 src/qt/forms/sendtopcodedialog.ui delete mode 100644 src/qt/lelantuscoincontroldialog.cpp delete mode 100644 src/qt/lelantuscoincontroldialog.h delete mode 100644 src/qt/lelantusdialog.cpp delete mode 100644 src/qt/lelantusdialog.h delete mode 100644 src/qt/lelantusmodel.cpp delete mode 100644 src/qt/lelantusmodel.h delete mode 100644 src/qt/pcodemodel.cpp delete mode 100644 src/qt/pcodemodel.h delete mode 100644 src/qt/sendtopcodedialog.cpp delete mode 100644 src/qt/sendtopcodedialog.h diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index 613cc3178e..8967a4ba4c 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -116,10 +116,8 @@ QT_FORMS_UI = \ qt/forms/debugwindow.ui \ qt/forms/sendcoinsdialog.ui \ qt/forms/sendcoinsentry.ui \ - qt/forms/sendtopcodedialog.ui \ qt/forms/signverifymessagedialog.ui \ - qt/forms/transactiondescdialog.ui \ - qt/forms/lelantusdialog.ui + qt/forms/transactiondescdialog.ui QT_MOC_CPP = \ qt/moc_addressbookpage.cpp \ @@ -162,7 +160,6 @@ QT_MOC_CPP = \ qt/moc_rpcconsole.cpp \ qt/moc_sendcoinsdialog.cpp \ qt/moc_sendcoinsentry.cpp \ - qt/moc_sendtopcodedialog.cpp \ qt/moc_signverifymessagedialog.cpp \ qt/moc_splashscreen.cpp \ qt/moc_trafficgraphwidget.cpp \ @@ -175,12 +172,8 @@ QT_MOC_CPP = \ qt/moc_walletframe.cpp \ qt/moc_walletmodel.cpp \ qt/moc_walletview.cpp \ - qt/moc_lelantusmodel.cpp \ - qt/moc_lelantusdialog.cpp \ - qt/moc_lelantuscoincontroldialog.cpp \ qt/moc_automintmodel.cpp \ qt/moc_automintnotification.cpp \ - qt/moc_pcodemodel.cpp \ qt/moc_sparkmodel.cpp BITCOIN_MM = \ @@ -233,7 +226,6 @@ BITCOIN_QT_H = \ qt/optionsmodel.h \ qt/overviewpage.h \ qt/paymentserver.h \ - qt/pcodemodel.h \ qt/peertablemodel.h \ qt/platformstyle.h \ qt/qvalidatedlineedit.h \ @@ -244,7 +236,6 @@ BITCOIN_QT_H = \ qt/rpcconsole.h \ qt/sendcoinsdialog.h \ qt/sendcoinsentry.h \ - qt/sendtopcodedialog.h \ qt/signverifymessagedialog.h \ qt/splashscreen.h \ qt/trafficgraphwidget.h \ @@ -260,9 +251,6 @@ BITCOIN_QT_H = \ qt/walletmodeltransaction.h \ qt/walletview.h \ qt/winshutdownmonitor.h \ - qt/lelantusmodel.h \ - qt/lelantusdialog.h \ - qt/lelantuscoincontroldialog.h \ qt/automintmodel.h \ qt/sparkmodel.h @@ -430,14 +418,12 @@ BITCOIN_QT_WALLET_CPP = \ qt/manualmintdialog.cpp \ qt/openuridialog.cpp \ qt/overviewpage.cpp \ - qt/pcodemodel.cpp \ qt/paymentserver.cpp \ qt/receivecoinsdialog.cpp \ qt/receiverequestdialog.cpp \ qt/recentrequeststablemodel.cpp \ qt/sendcoinsdialog.cpp \ qt/sendcoinsentry.cpp \ - qt/sendtopcodedialog.cpp \ qt/signverifymessagedialog.cpp \ qt/transactiondesc.cpp \ qt/transactiondescdialog.cpp \ @@ -450,9 +436,6 @@ BITCOIN_QT_WALLET_CPP = \ qt/walletmodeltransaction.cpp \ qt/masternodelist.cpp \ qt/walletview.cpp \ - qt/lelantusmodel.cpp \ - qt/lelantusdialog.cpp \ - qt/lelantuscoincontroldialog.cpp \ qt/automintmodel.cpp \ qt/sparkmodel.cpp diff --git a/src/qt/automintdialog.cpp b/src/qt/automintdialog.cpp index 42d52cfd4f..73ee1f80bf 100644 --- a/src/qt/automintdialog.cpp +++ b/src/qt/automintdialog.cpp @@ -3,7 +3,6 @@ #include "automintdialog.h" #include "automintmodel.h" #include "bitcoinunits.h" -#include "lelantusmodel.h" #include "sparkmodel.h" #include "ui_automintdialog.h" @@ -11,148 +10,6 @@ #include #include -AutoMintDialog::AutoMintDialog(AutoMintMode mode, QWidget *parent) : - QDialog(parent), - ui(new Ui::AutoMintDialog), - model(0), - lelantusModel(0), - requiredPassphase(true), - progress(AutoMintProgress::Start), - mode(mode) -{ - ENTER_CRITICAL_SECTION(cs_main); - ENTER_CRITICAL_SECTION(pwalletMain->cs_wallet); - - ui->setupUi(this); - ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Anonymize")); - ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel")); -} - -AutoMintDialog::~AutoMintDialog() -{ - if (lelantusModel) { - LEAVE_CRITICAL_SECTION(lelantusModel->cs); - } - - LEAVE_CRITICAL_SECTION(pwalletMain->cs_wallet); - LEAVE_CRITICAL_SECTION(cs_main); -} - -void AutoMintDialog::accept() -{ - ensureLelantusModel(); - - ui->buttonBox->setVisible(false); - ui->passEdit->setVisible(false); - ui->passLabel->setVisible(false); - ui->lockWarningLabel->setVisible(false); - ui->lockCheckBox->setVisible(false); - - if (requiredPassphase) { - auto rawPassphase = ui->passEdit->text().toStdString(); - SecureString passphase(rawPassphase.begin(), rawPassphase.end()); - auto lock = ui->lockCheckBox->isChecked(); - - progress = AutoMintProgress::Unlocking; - repaint(); - - if (!lelantusModel->unlockWallet(passphase, lock ? 0 : 60 * 1000)) { - QMessageBox::critical(this, tr("Wallet unlock failed"), - tr("The passphrase was incorrect.")); - QDialog::reject(); - return; - } - } - - progress = AutoMintProgress::Minting; - repaint(); - - AutoMintAck status; - CAmount minted = 0; - QString error; - - try { - minted = lelantusModel->mintAll(); - status = AutoMintAck::Success; - } catch (std::runtime_error const &e) { - status = AutoMintAck::FailToMint; - error = e.what(); - QMessageBox::critical(this, tr("Unable to generate mint"), - tr(error.toLocal8Bit().data())); - } - - QDialog::accept(); - - lelantusModel->sendAckMintAll(status, minted, error); -} - -int AutoMintDialog::exec() -{ - ensureLelantusModel(); - if (lelantusModel->getMintableAmount() <= 0) { - lelantusModel->sendAckMintAll(AutoMintAck::NotEnoughFund); - return 0; - } - - return QDialog::exec(); -} - -void AutoMintDialog::reject() -{ - ensureLelantusModel(); - lelantusModel->sendAckMintAll(AutoMintAck::UserReject); - QDialog::reject(); -} - -void AutoMintDialog::setModel(WalletModel *model) -{ - this->model = model; - if (!this->model) { - return; - } - - lelantusModel = this->model->getLelantusModel(); - if (!lelantusModel) { - return; - } - - ENTER_CRITICAL_SECTION(lelantusModel->cs); - - if (this->model->getEncryptionStatus() != WalletModel::Locked) { - ui->passLabel->setVisible(false); - ui->passEdit->setVisible(false); - ui->lockCheckBox->setVisible(false); - ui->lockWarningLabel->setText(QString(tr("Do you want to anonymize all transparent funds?"))); - - requiredPassphase = false; - } -} - -void AutoMintDialog::paintEvent(QPaintEvent *event) -{ - QPainter painter; - painter.begin(this); - - if (progress != AutoMintProgress::Start) { - auto progressMessage = progress == AutoMintProgress::Unlocking ? tr("Unlocking wallet...") : tr("Anonymizing..."); - auto size = QFontMetrics(painter.font()).size(Qt::TextSingleLine, progressMessage); - painter.drawText( - (width() - size.width()) / 2, - (height() - size.height()) / 2, - QString(progressMessage)); - } - - QWidget::paintEvent(event); - painter.end(); -} - -void AutoMintDialog::ensureLelantusModel() -{ - if (!lelantusModel) { - throw std::runtime_error("Lelantus model is not set"); - } -} - AutoMintSparkDialog::AutoMintSparkDialog(AutoMintSparkMode mode, QWidget *parent) : QDialog(parent), ui(new Ui::AutoMintDialog), diff --git a/src/qt/automintdialog.h b/src/qt/automintdialog.h index afc3857da9..0d36080cab 100644 --- a/src/qt/automintdialog.h +++ b/src/qt/automintdialog.h @@ -7,50 +7,10 @@ #include #include -enum class AutoMintMode : uint8_t { - MintAll, // come from overview page - AutoMintAll // come from notification -}; - namespace Ui { class AutoMintDialog; } -class AutoMintDialog : public QDialog -{ - Q_OBJECT; - -public: - explicit AutoMintDialog(AutoMintMode mode, QWidget *parent = 0); - ~AutoMintDialog(); - -public: - int exec(); - void setModel(WalletModel *model); - - void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; - -private Q_SLOTS: - void accept(); - void reject(); - -private: - enum class AutoMintProgress : uint8_t { - Start, - Unlocking, - Minting - }; - - Ui::AutoMintDialog *ui; - WalletModel *model; - LelantusModel *lelantusModel; - bool requiredPassphase; - AutoMintProgress progress; - AutoMintMode mode; - - void ensureLelantusModel(); -}; - enum class AutoMintSparkMode : uint8_t { MintAll, // come from overview page AutoMintAll // come from notification diff --git a/src/qt/automintmodel.cpp b/src/qt/automintmodel.cpp index 98bf0f55c4..a78c55dc26 100644 --- a/src/qt/automintmodel.cpp +++ b/src/qt/automintmodel.cpp @@ -1,4 +1,3 @@ -#include "../lelantus.h" #include "../masternode-sync.h" #include "../validation.h" #include "../wallet/wallet.h" @@ -6,7 +5,6 @@ #include "automintmodel.h" #include "bitcoinunits.h" #include "guiconstants.h" -#include "lelantusmodel.h" #include "sparkmodel.h" #include "optionsmodel.h" @@ -168,190 +166,6 @@ void IncomingFundNotifier::unsubscribeFromCoreSignals() boost::bind(IncomingFundNotifyBlockTip, this, _1, _2)); } -AutoMintModel::AutoMintModel( - LelantusModel *_lelantusModel, - OptionsModel *_optionsModel, - CWallet *_wallet, - QObject *parent) : - QObject(parent), - lelantusModel(_lelantusModel), - optionsModel(_optionsModel), - wallet(_wallet), - autoMintState(AutoMintState::Disabled), - autoMintCheckTimer(0), - notifier(0) -{ - autoMintCheckTimer = new QTimer(this); - autoMintCheckTimer->setSingleShot(false); - - connect(autoMintCheckTimer, &QTimer::timeout, [this]{ checkAutoMint(); }); - - notifier = new IncomingFundNotifier(wallet, this); - - connect(notifier, &IncomingFundNotifier::matureFund, this, &AutoMintModel::startAutoMint); - - connect(optionsModel, &OptionsModel::autoAnonymizeChanged, this, &AutoMintModel::updateAutoMintOption); -} - -AutoMintModel::~AutoMintModel() -{ - delete autoMintCheckTimer; - - autoMintCheckTimer = nullptr; -} - -bool AutoMintModel::isAnonymizing() const -{ - return autoMintState == AutoMintState::Anonymizing; -} - -void AutoMintModel::ackMintAll(AutoMintAck ack, CAmount minted, QString error) -{ - bool mint = false; - { - LOCK(lelantusModel->cs); - if (autoMintState == AutoMintState::Disabled) { - // Do nothing - return; - } else if (ack == AutoMintAck::WaitUserToActive) { - autoMintState = AutoMintState::WaitingUserToActivate; - } else if (ack == AutoMintAck::AskToMint) { - autoMintState = AutoMintState::Anonymizing; - autoMintCheckTimer->stop(); - mint = true; - } else { - autoMintState = AutoMintState::WaitingIncomingFund; - autoMintCheckTimer->stop(); - } - - processAutoMintAck(ack, minted, error); - } - - if (mint) { - lelantusModel->mintAll(AutoMintMode::AutoMintAll); - } -} - -void AutoMintModel::checkAutoMint(bool force) -{ - // if lelantus is not allow or client is in initial syncing state then wait - // except user force to check - if (!force) { - if (!masternodeSync.IsBlockchainSynced()) { - return; - } - - bool allowed = lelantus::IsLelantusAllowed(); - if (!allowed) { - return; - } - } - - { - LOCK(lelantusModel->cs); - - if (fReindex) { - return; - } - - switch (autoMintState) { - case AutoMintState::Disabled: - case AutoMintState::WaitingIncomingFund: - if (force) { - break; - } - autoMintCheckTimer->stop(); - return; - case AutoMintState::WaitingUserToActivate: - break; - case AutoMintState::Anonymizing: - return; - default: - throw std::runtime_error("Unknown auto mint state"); - } - - autoMintState = AutoMintState::Anonymizing; - } - - Q_EMIT requireShowAutomintNotification(); -} - -void AutoMintModel::startAutoMint() -{ - if (autoMintCheckTimer->isActive()) { - return; - } - - if (!optionsModel->getAutoAnonymize()) { - return; - } - - CAmount mintable = 0; - { - LOCK2(cs_main, wallet->cs_wallet); - mintable = lelantusModel->getMintableAmount(); - } - - if (mintable > 0) { - autoMintState = AutoMintState::WaitingUserToActivate; - - autoMintCheckTimer->start(MODEL_UPDATE_DELAY); - } else { - autoMintState = AutoMintState::WaitingIncomingFund; - } -} - -void AutoMintModel::updateAutoMintOption(bool enabled) -{ - LOCK2(cs_main, wallet->cs_wallet); - LOCK(lelantusModel->cs); - - if (enabled) { - if (autoMintState == AutoMintState::Disabled) { - startAutoMint(); - } - } else { - if (autoMintCheckTimer->isActive()) { - autoMintCheckTimer->stop(); - } - - // stop mint - autoMintState = AutoMintState::Disabled; - - Q_EMIT closeAutomintNotification(); - } -} - -void AutoMintModel::processAutoMintAck(AutoMintAck ack, CAmount minted, QString error) -{ - QPair msgParams; - msgParams.second = CClientUIInterface::MSG_WARNING; - - switch (ack) - { - case AutoMintAck::Success: - msgParams.first = tr("Successfully anonymized %1") - .arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), minted)); - msgParams.second = CClientUIInterface::MSG_INFORMATION; - break; - case AutoMintAck::WaitUserToActive: - case AutoMintAck::NotEnoughFund: - return; - case AutoMintAck::FailToMint: - msgParams.first = tr("Fail to mint, %1").arg(error); - msgParams.second = CClientUIInterface::MSG_ERROR; - break; - case AutoMintAck::FailToUnlock: - msgParams.first = tr("Fail to unlock wallet"); - msgParams.second = CClientUIInterface::MSG_ERROR; - break; - default: - return; - }; - - Q_EMIT message(tr("Auto Anonymize"), msgParams.first, msgParams.second); -} - AutoMintSparkModel::AutoMintSparkModel( SparkModel *_sparkModel, OptionsModel *_optionsModel, diff --git a/src/qt/automintmodel.h b/src/qt/automintmodel.h index 5b43de462b..128337299f 100644 --- a/src/qt/automintmodel.h +++ b/src/qt/automintmodel.h @@ -12,29 +12,10 @@ #include #include -class LelantusModel; class SparkModel; class OptionsModel; class CWallet; -enum class AutoMintState : uint8_t { - Disabled, - WaitingIncomingFund, - WaitingUserToActivate, - Anonymizing -}; - -enum class AutoMintAck : uint8_t { - AskToMint, - Success, - WaitUserToActive, - FailToMint, - NotEnoughFund, - UserReject, - FailToUnlock, - Close -}; - class IncomingFundNotifier : public QObject { Q_OBJECT; @@ -67,51 +48,6 @@ public Q_SLOTS: int64_t lastUpdateTime; }; -class AutoMintModel : public QObject -{ - Q_OBJECT; - -public: - explicit AutoMintModel( - LelantusModel *lelantusModel, - OptionsModel *optionsModel, - CWallet *wallet, - QObject *parent = 0); - - ~AutoMintModel(); - -public: - bool isAnonymizing() const; - -public Q_SLOTS: - void ackMintAll(AutoMintAck ack, CAmount minted, QString error); - void checkAutoMint(bool force = false); - - void startAutoMint(); - - void updateAutoMintOption(bool); - -Q_SIGNALS: - void message(const QString &title, const QString &message, unsigned int style); - - void requireShowAutomintNotification(); - void closeAutomintNotification(); - -private: - void processAutoMintAck(AutoMintAck ack, CAmount minted, QString error); - -private: - LelantusModel *lelantusModel; - OptionsModel *optionsModel; - CWallet *wallet; - - AutoMintState autoMintState; - - QTimer *autoMintCheckTimer; - - IncomingFundNotifier *notifier; -}; - enum class AutoMintSparkState : uint8_t { Disabled, WaitingIncomingFund, diff --git a/src/qt/automintnotification.cpp b/src/qt/automintnotification.cpp index 4ff0786bd2..8cf9a00215 100644 --- a/src/qt/automintnotification.cpp +++ b/src/qt/automintnotification.cpp @@ -5,59 +5,6 @@ #include -AutomintNotification::AutomintNotification(QWidget *parent) : - QDialog(parent), - ui(new Ui::AutomintNotification), - lelantusModel(nullptr) -{ - ui->setupUi(this); - ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Anonymize")); - ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Dismiss")); - - setWindowFlags(windowFlags() | Qt::FramelessWindowHint); -} - -AutomintNotification::~AutomintNotification() -{ - delete ui; -} - -void AutomintNotification::setModel(WalletModel *model) -{ - if (model) { - lelantusModel = model->getLelantusModel(); - - if (!lelantusModel) { - return; - } - - auto automintModel = lelantusModel->getAutoMintModel(); - if (!automintModel) { - return; - } - - connect(this, &AutomintNotification::ackMintAll, automintModel, &AutoMintModel::ackMintAll); - } -} - -bool AutomintNotification::close() -{ - Q_EMIT ackMintAll(AutoMintAck::NotEnoughFund, 0, QString()); - return QDialog::close(); -} - -void AutomintNotification::accept() -{ - Q_EMIT ackMintAll(AutoMintAck::AskToMint, 0, QString()); - QDialog::accept(); -} - -void AutomintNotification::reject() -{ - Q_EMIT ackMintAll(AutoMintAck::UserReject, 0, QString()); - QDialog::reject(); -} - AutomintSparkNotification::AutomintSparkNotification(QWidget *parent) : QDialog(parent), ui(new Ui::AutomintNotification), diff --git a/src/qt/automintnotification.h b/src/qt/automintnotification.h index cfbc19818c..c1aa87e8cb 100644 --- a/src/qt/automintnotification.h +++ b/src/qt/automintnotification.h @@ -1,7 +1,6 @@ #ifndef FIRO_QT_AUTOMINTNOTIFICATION_H #define FIRO_QT_AUTOMINTNOTIFICATION_H -#include "lelantusmodel.h" #include "sparkmodel.h" #include "walletmodel.h" @@ -11,31 +10,6 @@ namespace Ui { class AutomintNotification; } -class AutomintNotification : public QDialog -{ - Q_OBJECT; - -public: - explicit AutomintNotification(QWidget *parent = 0); - ~AutomintNotification(); - -public: - void setModel(WalletModel *model); - -Q_SIGNALS: - void ackMintAll(AutoMintAck, CAmount, QString); - -public Q_SLOTS: - bool close(); - -private Q_SLOTS: - void accept(); - void reject(); - -private: - Ui::AutomintNotification *ui; - LelantusModel *lelantusModel; -}; class AutomintSparkNotification : public QDialog { diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index b07dbbfe66..63329f788b 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -381,7 +381,6 @@ void BitcoinGUI::createActions() connect(historyAction, &QAction::triggered, this, [this]{ showNormalIfMinimized(); }); connect(historyAction, &QAction::triggered, this, &BitcoinGUI::gotoHistoryPage); - connect(lelantusAction, &QAction::triggered, this, &BitcoinGUI::gotoLelantusPage); #endif // ENABLE_WALLET quitAction = new QAction(tr("E&xit"), this); @@ -580,9 +579,6 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel) // be aware of the tray icon disable state change reported by the OptionsModel object. connect(optionsModel, &OptionsModel::hideTrayIconChanged, this, &BitcoinGUI::setTrayIconVisible); - // update lelantus page if option is changed. - connect(optionsModel, &OptionsModel::lelantusPageChanged, this, &BitcoinGUI::updateLelantusPage); - // initialize the disable state of the tray icon with the current value in the model. setTrayIconVisible(optionsModel->getHideTrayIcon()); } @@ -590,7 +586,6 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel) #ifdef ENABLE_WALLET auto blocks = clientModel->getNumBlocks(); checkZnodeVisibility(blocks); - checkLelantusVisibility(blocks); #endif // ENABLE_WALLET } } else { @@ -807,12 +802,6 @@ void BitcoinGUI::gotoSignMessageTab(QString addr) if (walletFrame) walletFrame->gotoSignMessageTab(addr); } -void BitcoinGUI::gotoLelantusPage() -{ - lelantusAction->setChecked(true); - if (walletFrame) walletFrame->gotoLelantusPage(); -} - void BitcoinGUI::gotoVerifyMessageTab(QString addr) { if (walletFrame) walletFrame->gotoVerifyMessageTab(addr); @@ -977,7 +966,6 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVer progressBar->setToolTip(tooltip); #ifdef ENABLE_WALLET - checkLelantusVisibility(count); checkZnodeVisibility(count); #endif // ENABLE_WALLET } @@ -1323,12 +1311,6 @@ void BitcoinGUI::showModalOverlay() modalOverlay->toggleVisibility(); } -void BitcoinGUI::updateLelantusPage() -{ - auto blocks = clientModel->getNumBlocks(); - checkLelantusVisibility(blocks); -} - static bool ThreadSafeMessageBox(BitcoinGUI *gui, const std::string& message, const std::string& caption, unsigned int style) { bool modal = (style & CClientUIInterface::MODAL); @@ -1371,30 +1353,6 @@ void BitcoinGUI::checkZnodeVisibility(int numBlocks) { } } -void BitcoinGUI::checkLelantusVisibility(int numBlocks) -{ - auto allowLelantusPage = false; - if (clientModel && clientModel->getOptionsModel()) { - allowLelantusPage = clientModel->getOptionsModel()->getLelantusPage(); - } - - allowLelantusPage &= lelantus::IsLelantusAllowed(numBlocks); - - if (allowLelantusPage != lelantusAction->isVisible()) { - if (!allowLelantusPage && lelantusAction->isChecked()) { -#ifdef ENABLE_WALLET - gotoOverviewPage(); -#endif // ENABLE_WALLET - } - lelantusAction->setVisible(allowLelantusPage); - } - -#ifdef ENABLE_WALLET - if (numBlocks == ::Params().GetConsensus().nSparkStartBlock) - walletFrame->updateAddressbook(); -#endif // ENABLE_WALLET -} - void BitcoinGUI::toggleNetworkActive() { if (clientModel) { diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index bb2db20668..62f23052aa 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -160,8 +160,7 @@ class BitcoinGUI : public QMainWindow /** Updates Znode visibility */ void checkZnodeVisibility(int numBlocks); - /** Updates Lelantus visibility */ - void checkLelantusVisibility(int numBlocks); + /** Update UI with latest network info from model. */ void updateNetworkState(); @@ -223,8 +222,6 @@ public Q_SLOTS: void gotoReceiveCoinsPage(); /** Switch to send coins page */ void gotoSendCoinsPage(QString addr = ""); - /** Switch to lelantus page */ - void gotoLelantusPage(); /** Show Sign/Verify Message dialog and switch to sign message tab */ void gotoSignMessageTab(QString addr = ""); @@ -273,9 +270,6 @@ public Q_SLOTS: void showModalOverlay(); - /** Update Lelantus page visibility */ - void updateLelantusPage(); - }; class UnitDisplayStatusBarControl : public QLabel diff --git a/src/qt/forms/lelantusdialog.ui b/src/qt/forms/lelantusdialog.ui deleted file mode 100644 index e6deeaa595..0000000000 --- a/src/qt/forms/lelantusdialog.ui +++ /dev/null @@ -1,1644 +0,0 @@ - - - LelantusDialog - - - - 0 - 0 - 914 - 699 - - - - Send Coins - - - - 8 - - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - 0 - - - 0 - - - 0 - - - 0 - - - 6 - - - - - 0 - - - 10 - - - 10 - - - - - 15 - - - - - - 0 - 0 - - - - - 75 - true - - - - font-weight:bold; - - - Coin Control Features - - - - - - - - - 8 - - - 10 - - - - - - - - Inputs... - - - false - - - - - - - automatically selected - - - 5 - - - - - - - - 75 - true - - - - color:red;font-weight:bold; - - - Insufficient funds! - - - 5 - - - - - - - Qt::Horizontal - - - - 40 - 1 - - - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 20 - - - 0 - - - 10 - - - - - 10 - - - 14 - - - 10 - - - 4 - - - 6 - - - - - - 75 - true - - - - Quantity: - - - 0 - - - - - - - IBeamCursor - - - Qt::ActionsContextMenu - - - 0 - - - 0 - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - - 75 - true - - - - Bytes: - - - - - - - IBeamCursor - - - Qt::ActionsContextMenu - - - 0 - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - - - 10 - - - 14 - - - 6 - - - 4 - - - 6 - - - - - - 75 - true - - - - Amount: - - - 0 - - - - - - - IBeamCursor - - - Qt::ActionsContextMenu - - - 0.00 FIRO - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - - 75 - true - - - - Dust: - - - - - - - IBeamCursor - - - Qt::ActionsContextMenu - - - no - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - - - 10 - - - 14 - - - 6 - - - 4 - - - 6 - - - - - - 75 - true - - - - Fee: - - - 0 - - - - - - - IBeamCursor - - - Qt::ActionsContextMenu - - - 0.00 FIRO - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - - - 10 - - - 14 - - - 6 - - - 4 - - - 6 - - - - - - 75 - true - - - - After Fee: - - - 0 - - - - - - - IBeamCursor - - - Qt::ActionsContextMenu - - - 0.00 FIRO - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - - 75 - true - - - - Change: - - - - - - - IBeamCursor - - - Qt::ActionsContextMenu - - - 0.00 FIRO - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - - - - - - - - 12 - - - QLayout::SetDefaultConstraint - - - 5 - - - 5 - - - - - If this is activated, but the change address is empty or invalid, change will be sent to a newly generated address. - - - Custom change address - - - - - - - false - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - - - 3 - - - - - - - - - Qt::Vertical - - - - 800 - 1 - - - - - - - - - - - - - - - 5 - - - 1 - - - 3 - - - - - - 0 - 25 - - - - Spendable: - - - - - - - - 0 - 25 - - - - Unspent: - - - - - - - - 300 - 0 - - - - 0.00000000 FIRO - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 25 - - - - Unconfirmed: - - - - - - - - 75 - true - - - - Global Lelantus Pool - - - - - - - - 100 - 0 - - - - 0 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 300 - 0 - - - - 0.00000000 FIRO - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 0 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 0 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 300 - 0 - - - - 0.00000000 FIRO - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 0 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 300 - 0 - - - - 0.00000000 FIRO - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - true - - - - 75 - true - - - - Your Anonymized Coins - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - 0 - - - - - - - 0 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 25 - - - - Total: - - - - - - - - 0 - 25 - - - - Total: - - - - - - - - 300 - 0 - - - - 0.00000000 FIRO - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Latest group: - - - - - - - 0 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - 0.00000000 FIRO - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 300 - - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - 10 - - - 10 - - - 10 - - - 0 - - - - - 0 - - - 0 - - - - - Amount to anonymize: - - - - - - - - - - FIRO - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - Available amount to anonymize 9999.99999999 FIRO - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 600 - - - - - - - - 0 - - - 0 - - - 0 - - - - - - - Qt::Horizontal - - - - - - - - - 0 - - - - - 0 - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 1 - 5 - - - - - - - - 10 - - - - - - 0 - 0 - - - - - 75 - true - - - - font-weight:bold; - - - Transaction Fee: - - - - - - - - - - - - - - Choose... - - - - - - - - - Qt::Vertical - - - - 1 - 1 - - - - - - - - - - - 75 - true - - - - Using the fallbackfee can result in sending a transaction that will take several hours or days (or never) to confirm. Consider choosing your fee manually or wait until your have validated the complete chain. - - - Warning: Fee estimation is currently not possible. - - - false - - - - - - - Qt::Horizontal - - - QSizePolicy::MinimumExpanding - - - - 40 - 20 - - - - - - - - collapse fee-settings - - - Hide - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - 10 - - - 4 - - - 10 - - - 4 - - - - - 6 - - - - - - - If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. - - - per kilobyte - - - true - - - groupCustomFee - - - - - - - If the custom fee is set to 1000 satoshis and the transaction is only 250 bytes, then "per kilobyte" only pays 250 satoshis in fee, while "total at least" pays 1000 satoshis. For transactions bigger than a kilobyte both pay by kilobyte. - - - each transaction at least - - - groupCustomFee - - - - - - - - - - Qt::Horizontal - - - - 1 - 1 - - - - - - - - - - - - Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for Firo transactions than the network can process. - - - - - - - - - - true - - - Paying only the minimum fee is just fine as long as there is less transaction volume than space in the blocks. But be aware that this can end up in a never confirming transaction once there is more demand for Firo transactions than the network can process. - - - (read the tooltip) - - - 5 - - - - - - - Qt::Horizontal - - - - 1 - 1 - - - - - - - - - - - - - - Recommended: - - - true - - - groupFee - - - - - - - Qt::Vertical - - - - 1 - 1 - - - - - - - - - - - - Custom: - - - groupFee - - - - - - - Qt::Vertical - - - - 1 - 1 - - - - - - - - - - 6 - - - 2 - - - - - - - - - - 2 - - - - - - - - - - - - - - (Smart fee not initialized yet. This usually takes a few blocks...) - - - 2 - - - - - - - Qt::Horizontal - - - - 1 - 1 - - - - - - - - - - - - - - Confirmation time target: - - - 2 - - - - - - - Qt::Vertical - - - - 1 - 1 - - - - - - - - - - 30 - - - - - 0 - - - 23 - - - 1 - - - 0 - - - Qt::Horizontal - - - false - - - false - - - QSlider::NoTicks - - - - - - - - - normal - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - (count) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - fast - - - - - - - - - - - - - Qt::Vertical - - - - 1 - 1 - - - - - - - - - - - - - - - Qt::Vertical - - - - 800 - 1 - - - - - - - - - - - - - - - - 150 - 0 - - - - Confirm the send action - - - Anonymize - - - false - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 3 - - - - - - - - - - QValidatedLineEdit - QLineEdit -
qvalidatedlineedit.h
-
- - BitcoinAmountField - QLineEdit -
bitcoinamountfield.h
- 1 -
-
- - - - - - - - -
diff --git a/src/qt/forms/sendtopcodedialog.ui b/src/qt/forms/sendtopcodedialog.ui deleted file mode 100644 index 119464a369..0000000000 --- a/src/qt/forms/sendtopcodedialog.ui +++ /dev/null @@ -1,277 +0,0 @@ - - - SendtoPcodeDialog - - - - 0 - 0 - 785 - 258 - - - - - 0 - 0 - - - - Send to RAP address - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - This is the first time you are sending to this RAP address: - - - - - - - TextLabel - - - - - - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Sunken - - - - - - - - - Qt::RichText - - - true - - - - - - - - - Status - - - - - - - - - TextLabel - - - - - - - Qt::Vertical - - - - 20 - 20 - - - - - - - - - - Lelantus balance - - - - - - - Qt::Horizontal - - - - 200 - 2 - - - - - - - - Connection transaction - - - - - - - Sends the connection transaction - - - Connect - - - - - - - notificationTxId - - - - - - - TextLabel - - - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Minimum - - - - 20 - 10 - - - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - Help - - - - .. - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Requires a notification tx to be confirmed - - - Send Now - - - - - - - true - - - Cancel - - - Cancel - - - - .. - - - false - - - - - - - - - - - - - - - - slot1() - - diff --git a/src/qt/lelantuscoincontroldialog.cpp b/src/qt/lelantuscoincontroldialog.cpp deleted file mode 100644 index 6837cf8f04..0000000000 --- a/src/qt/lelantuscoincontroldialog.cpp +++ /dev/null @@ -1,770 +0,0 @@ -// Copyright (c) 2020 The Firo Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "coincontroldialog.h" -#include "lelantuscoincontroldialog.h" -#include "ui_coincontroldialog.h" - -#include "addresstablemodel.h" -#include "bitcoinunits.h" -#include "guiutil.h" -#include "optionsmodel.h" -#include "platformstyle.h" -#include "txmempool.h" -#include "walletmodel.h" - -#include "wallet/coincontrol.h" -#include "init.h" -#include "policy/policy.h" -#include "validation.h" // For mempool -#include "wallet/wallet.h" - -#include // for 'map_list_of()' - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void CoinControlStorage::updateLabels(WalletModel *model, QDialog* dialog) -{ - if (!model) - return; - - // nPayAmount - CAmount nPayAmount = 0; - bool fDust = false; - CMutableTransaction txDummy; - for (const CAmount &amount : payAmounts) - { - nPayAmount += amount; - - if (amount > 0) - { - CTxOut txout(amount, (CScript)std::vector(24, 0)); - txDummy.vout.push_back(txout); - if (txout.IsDust(dustRelayFee)) - fDust = true; - } - } - - CAmount nAmount = 0; - CAmount nPayFee = 0; - CAmount nAfterFee = 0; - CAmount nChange = 0; - unsigned int nBytes = 0; - unsigned int nBytesInputs = 0; - double dPriority = 0; - double dPriorityInputs = 0; - unsigned int nQuantity = 0; - int nQuantityUncompressed = 0; - bool fAllowFree = false; - bool fWitness = false; - - std::vector vCoinControl; - std::vector vOutputs; - coinControl.ListSelected(vCoinControl); - model->getOutputs(vCoinControl, vOutputs); - - BOOST_FOREACH(const COutput& out, vOutputs) { - // unselect already spent, very unlikely scenario, this could happen - // when selected are spent elsewhere, like rpc or another computer - uint256 txhash = out.tx->GetHash(); - COutPoint outpt(txhash, out.i); - if (model->isSpent(outpt)) - { - coinControl.UnSelect(outpt); - continue; - } - - // Quantity - nQuantity++; - - // Amount - nAmount += out.tx->tx->vout[out.i].nValue; - - // Priority - dPriorityInputs += (double)out.tx->tx->vout[out.i].nValue * (out.nDepth+1); - - // Bytes - CTxDestination address; - int witnessversion = 0; - std::vector witnessprogram; - if (out.tx->tx->vout[out.i].scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) - { - nBytesInputs += (32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4); - fWitness = true; - } - else if(ExtractDestination(out.tx->tx->vout[out.i].scriptPubKey, address)) - { - CPubKey pubkey; - CKeyID *keyid = boost::get(&address); - if (keyid && model->getPubKey(*keyid, pubkey)) - { - nBytesInputs += (pubkey.IsCompressed() ? 148 : 180); - if (!pubkey.IsCompressed()) - nQuantityUncompressed++; - } - else - nBytesInputs += 148; // in all error cases, simply assume 148 here - } - else nBytesInputs += 148; - } - - // calculation - if (nQuantity > 0) - { - // Bytes - nBytes = nBytesInputs + ((payAmounts.size() > 0 ? payAmounts.size() + 1 : 2) * 34) + 10; // always assume +1 output for change here - if (fWitness) - { - // there is some fudging in these numbers related to the actual virtual transaction size calculation that will keep this estimate from being exact. - // usually, the result will be an overestimate within a couple of satoshis so that the confirmation dialog ends up displaying a slightly smaller fee. - // also, the witness stack size value value is a variable sized integer. usually, the number of stack items will be well under the single byte var int limit. - nBytes += 2; // account for the serialized marker and flag bytes - nBytes += nQuantity; // account for the witness byte that holds the number of stack items for each input. - } - - // in the subtract fee from amount case, we can tell if zero change already and subtract the bytes, so that fee calculation afterwards is accurate - if (fSubtractFeeFromAmount) - if (nAmount - nPayAmount == 0) - nBytes -= 34; - - // Fee - nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, mempool); - if (nPayFee > 0 && coinControl.nMinimumTotalFee > nPayFee) - nPayFee = coinControl.nMinimumTotalFee; - - - // Allow free? (require at least hard-coded threshold and default to that if no estimate) - double mempoolEstimatePriority = mempool.estimateSmartPriority(nTxConfirmTarget); - dPriority = dPriorityInputs / (nBytes - nBytesInputs + (nQuantityUncompressed * 29)); // 29 = 180 - 151 (uncompressed public keys are over the limit. max 151 bytes of the input are ignored for priority) - double dPriorityNeeded = std::max(mempoolEstimatePriority, AllowFreeThreshold()); - fAllowFree = (dPriority >= dPriorityNeeded); - - if (fSendFreeTransactions) - if (fAllowFree && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE) - nPayFee = 0; - - if (nPayAmount > 0) - { - nChange = nAmount - nPayAmount; - if (!fSubtractFeeFromAmount) - nChange -= nPayFee; - - // Never create dust outputs; if we would, just add the dust to the fee. - if (nChange > 0 && nChange < MIN_CHANGE) - { - CTxOut txout(nChange, (CScript)std::vector(24, 0)); - if (txout.IsDust(dustRelayFee)) - { - if (fSubtractFeeFromAmount) // dust-change will be raised until no dust - nChange = txout.GetDustThreshold(dustRelayFee); - else - { - nPayFee += nChange; - nChange = 0; - } - } - } - - if (nChange == 0 && !fSubtractFeeFromAmount) - nBytes -= 34; - } - - // after fee - nAfterFee = std::max(nAmount - nPayFee, 0); - } - - // actually update labels - int nDisplayUnit = BitcoinUnits::BTC; - if (model && model->getOptionsModel()) - nDisplayUnit = model->getOptionsModel()->getDisplayUnit(); - - QLabel *l1 = dialog->findChild("labelCoinControlQuantity"); - QLabel *l2 = dialog->findChild("labelCoinControlAmount"); - QLabel *l3 = dialog->findChild("labelCoinControlFee"); - QLabel *l4 = dialog->findChild("labelCoinControlAfterFee"); - QLabel *l5 = dialog->findChild("labelCoinControlBytes"); - QLabel *l7 = dialog->findChild("labelCoinControlLowOutput"); - QLabel *l8 = dialog->findChild("labelCoinControlChange"); - - // enable/disable "dust" and "change" - dialog->findChild("labelCoinControlLowOutputText")->setEnabled(nPayAmount > 0); - dialog->findChild("labelCoinControlLowOutput") ->setEnabled(nPayAmount > 0); - dialog->findChild("labelCoinControlChangeText") ->setEnabled(nPayAmount > 0); - dialog->findChild("labelCoinControlChange") ->setEnabled(nPayAmount > 0); - - // stats - l1->setText(QString::number(nQuantity)); // Quantity - l2->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nAmount)); // Amount - l3->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nPayFee)); // Fee - l4->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nAfterFee)); // After Fee - l5->setText(((nBytes > 0) ? ASYMP_UTF8 : "") + QString::number(nBytes)); // Bytes - l7->setText(fDust ? tr("yes") : tr("no")); // Dust - l8->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nChange)); // Change - if (nPayFee > 0 && (coinControl.nMinimumTotalFee < nPayFee)) - { - l3->setText(ASYMP_UTF8 + l3->text()); - l4->setText(ASYMP_UTF8 + l4->text()); - if (nChange > 0 && !fSubtractFeeFromAmount) - l8->setText(ASYMP_UTF8 + l8->text()); - } - - // turn label red when dust - l7->setStyleSheet((fDust) ? "color:red;" : ""); - - // tool tips - QString toolTipDust = tr("This label turns red if any recipient receives an amount smaller than the current dust threshold."); - - // how many satoshis the estimated fee can vary per byte we guess wrong - double dFeeVary; - if (payTxFee.GetFeePerK() > 0) - dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), payTxFee.GetFeePerK()) / 1000; - else { - dFeeVary = (double)std::max(CWallet::GetRequiredFee(1000), mempool.estimateSmartFee(nTxConfirmTarget).GetFeePerK()) / 1000; - } - QString toolTip4 = tr("Can vary +/- %1 satoshi(s) per input.").arg(dFeeVary); - - l3->setToolTip(toolTip4); - l4->setToolTip(toolTip4); - l7->setToolTip(toolTipDust); - l8->setToolTip(toolTip4); - dialog->findChild("labelCoinControlFeeText") ->setToolTip(l3->toolTip()); - dialog->findChild("labelCoinControlAfterFeeText") ->setToolTip(l4->toolTip()); - dialog->findChild("labelCoinControlBytesText") ->setToolTip(l5->toolTip()); - dialog->findChild("labelCoinControlLowOutputText")->setToolTip(l7->toolTip()); - dialog->findChild("labelCoinControlChangeText") ->setToolTip(l8->toolTip()); - - // Insufficient funds - QLabel *label = dialog->findChild("labelCoinControlInsuffFunds"); - if (label) - label->setVisible(nChange < 0); -} - -CoinControlStorage::CoinControlStorage() -{ -} - -LelantusCoinControlDialog::LelantusCoinControlDialog( - CoinControlStorage *_storage, - const PlatformStyle *_platformStyle, - QWidget *parent) : - QDialog(parent), - storage(_storage), - ui(new Ui::CoinControlDialog), - model(0), - platformStyle(_platformStyle) -{ - ui->setupUi(this); - - // context menu actions - QAction *copyAddressAction = new QAction(tr("Copy address"), this); - QAction *copyLabelAction = new QAction(tr("Copy label"), this); - QAction *copyAmountAction = new QAction(tr("Copy amount"), this); - copyTransactionHashAction = new QAction(tr("Copy transaction ID"), this); // we need to enable/disable this - lockAction = new QAction(tr("Lock unspent"), this); // we need to enable/disable this - unlockAction = new QAction(tr("Unlock unspent"), this); // we need to enable/disable this - - // context menu - contextMenu = new QMenu(this); - contextMenu->addAction(copyAddressAction); - contextMenu->addAction(copyLabelAction); - contextMenu->addAction(copyAmountAction); - contextMenu->addAction(copyTransactionHashAction); - contextMenu->addSeparator(); - contextMenu->addAction(lockAction); - contextMenu->addAction(unlockAction); - - // context menu signals - connect(ui->treeWidget, &QWidget::customContextMenuRequested, this, &LelantusCoinControlDialog::showMenu); - connect(copyAddressAction, &QAction::triggered, this, &LelantusCoinControlDialog::copyAddress); - connect(copyLabelAction, &QAction::triggered, this, &LelantusCoinControlDialog::copyLabel); - connect(copyAmountAction, &QAction::triggered, this, &LelantusCoinControlDialog::copyAmount); - connect(copyTransactionHashAction, &QAction::triggered, this, &LelantusCoinControlDialog::copyTransactionHash); - connect(lockAction, &QAction::triggered, this, &LelantusCoinControlDialog::lockCoin); - connect(unlockAction, &QAction::triggered, this, &LelantusCoinControlDialog::unlockCoin); - - // clipboard actions - QAction *clipboardQuantityAction = new QAction(tr("Copy quantity"), this); - QAction *clipboardAmountAction = new QAction(tr("Copy amount"), this); - QAction *clipboardFeeAction = new QAction(tr("Copy fee"), this); - QAction *clipboardAfterFeeAction = new QAction(tr("Copy after fee"), this); - QAction *clipboardBytesAction = new QAction(tr("Copy bytes"), this); - QAction *clipboardLowOutputAction = new QAction(tr("Copy dust"), this); - QAction *clipboardChangeAction = new QAction(tr("Copy change"), this); - - connect(clipboardQuantityAction, &QAction::triggered, this, &LelantusCoinControlDialog::clipboardQuantity); - connect(clipboardAmountAction, &QAction::triggered, this, &LelantusCoinControlDialog::clipboardAmount); - connect(clipboardFeeAction, &QAction::triggered, this, &LelantusCoinControlDialog::clipboardFee); - connect(clipboardAfterFeeAction, &QAction::triggered, this, &LelantusCoinControlDialog::clipboardAfterFee); - connect(clipboardBytesAction, &QAction::triggered, this, &LelantusCoinControlDialog::clipboardBytes); - connect(clipboardLowOutputAction, &QAction::triggered, this, &LelantusCoinControlDialog::clipboardLowOutput); - connect(clipboardChangeAction, &QAction::triggered, this, &LelantusCoinControlDialog::clipboardChange); - - ui->labelCoinControlQuantity->addAction(clipboardQuantityAction); - ui->labelCoinControlAmount->addAction(clipboardAmountAction); - ui->labelCoinControlFee->addAction(clipboardFeeAction); - ui->labelCoinControlAfterFee->addAction(clipboardAfterFeeAction); - ui->labelCoinControlBytes->addAction(clipboardBytesAction); - ui->labelCoinControlLowOutput->addAction(clipboardLowOutputAction); - ui->labelCoinControlChange->addAction(clipboardChangeAction); - - // toggle tree/list mode - connect(ui->radioTreeMode, &QRadioButton::toggled, this, &LelantusCoinControlDialog::radioTreeMode); - connect(ui->radioListMode, &QRadioButton::toggled, this, &LelantusCoinControlDialog::radioListMode); - - // click on checkbox - connect(ui->treeWidget, &QTreeWidget::itemChanged, this, &LelantusCoinControlDialog::viewItemChanged); - - // click on header -#if QT_VERSION < 0x050000 - ui->treeWidget->header()->setClickable(true); -#else - ui->treeWidget->header()->setSectionsClickable(true); -#endif - connect(ui->treeWidget->header(), &QHeaderView::sectionClicked, this, &LelantusCoinControlDialog::headerSectionClicked); - - // ok button - connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &LelantusCoinControlDialog::buttonBoxClicked); - - // (un)select all - connect(ui->pushButtonSelectAll, &QPushButton::clicked, this, &LelantusCoinControlDialog::buttonSelectAllClicked); - - // change coin control first column label due Qt4 bug. - // see https://github.com/bitcoin/bitcoin/issues/5716 - ui->treeWidget->headerItem()->setText(COLUMN_CHECKBOX, QString()); - - ui->treeWidget->setColumnWidth(COLUMN_CHECKBOX, 84); - ui->treeWidget->setColumnWidth(COLUMN_AMOUNT, 110); - ui->treeWidget->setColumnWidth(COLUMN_LABEL, 190); - ui->treeWidget->setColumnWidth(COLUMN_ADDRESS, 320); - ui->treeWidget->setColumnWidth(COLUMN_DATE, 130); - ui->treeWidget->setColumnWidth(COLUMN_CONFIRMATIONS, 110); - ui->treeWidget->setColumnHidden(COLUMN_TXHASH, true); // store transaction hash in this column, but don't show it - ui->treeWidget->setColumnHidden(COLUMN_VOUT_INDEX, true); // store vout index in this column, but don't show it - - // default view is sorted by amount desc - sortView(COLUMN_AMOUNT, Qt::DescendingOrder); - - // restore list mode and sortorder as a convenience feature - QSettings settings; - if (settings.contains("nCoinControlMode") && !settings.value("nCoinControlMode").toBool()) - ui->radioTreeMode->click(); - if (settings.contains("nCoinControlSortColumn") && settings.contains("nCoinControlSortOrder")) - sortView(settings.value("nCoinControlSortColumn").toInt(), ((Qt::SortOrder)settings.value("nCoinControlSortOrder").toInt())); -} - -LelantusCoinControlDialog::~LelantusCoinControlDialog() -{ - QSettings settings; - settings.setValue("nCoinControlMode", ui->radioListMode->isChecked()); - settings.setValue("nCoinControlSortColumn", sortColumn); - settings.setValue("nCoinControlSortOrder", (int)sortOrder); - - delete ui; -} - -void LelantusCoinControlDialog::setModel(WalletModel *_model) -{ - this->model = _model; - - if (_model && _model->getOptionsModel() && _model->getAddressTableModel()) { - updateView(); - updateLabelLocked(); - storage->updateLabels(_model, this); - } -} - -// ok button -void LelantusCoinControlDialog::buttonBoxClicked(QAbstractButton* button) -{ - if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) - done(QDialog::Accepted); // closes the dialog -} - -// (un)select all -void LelantusCoinControlDialog::buttonSelectAllClicked() -{ - Qt::CheckState state = Qt::Checked; - for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) - { - if (ui->treeWidget->topLevelItem(i)->checkState(COLUMN_CHECKBOX) != Qt::Unchecked) - { - state = Qt::Unchecked; - break; - } - } - ui->treeWidget->setEnabled(false); - for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) - if (ui->treeWidget->topLevelItem(i)->checkState(COLUMN_CHECKBOX) != state) - ui->treeWidget->topLevelItem(i)->setCheckState(COLUMN_CHECKBOX, state); - ui->treeWidget->setEnabled(true); - if (state == Qt::Unchecked) { - storage->coinControl.UnSelectAll(); // just to be sure - } - - storage->updateLabels(model, this); -} - -// context menu -void LelantusCoinControlDialog::showMenu(const QPoint &point) -{ - QTreeWidgetItem *item = ui->treeWidget->itemAt(point); - if(item) - { - contextMenuItem = item; - - // disable some items (like Copy Transaction ID, lock, unlock) for tree roots in context menu - if (item->text(COLUMN_TXHASH).length() == 64) // transaction hash is 64 characters (this means its a child node, so its not a parent node in tree mode) - { - copyTransactionHashAction->setEnabled(true); - if (model->isLockedCoin(uint256S(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt())) - { - lockAction->setEnabled(false); - unlockAction->setEnabled(true); - } - else - { - lockAction->setEnabled(true); - unlockAction->setEnabled(false); - } - } - else // this means click on parent node in tree mode -> disable all - { - copyTransactionHashAction->setEnabled(false); - lockAction->setEnabled(false); - unlockAction->setEnabled(false); - } - - // show context menu - contextMenu->exec(QCursor::pos()); - } -} - -// context menu action: copy amount -void LelantusCoinControlDialog::copyAmount() -{ - GUIUtil::setClipboard(BitcoinUnits::removeSpaces(contextMenuItem->text(COLUMN_AMOUNT))); -} - -// context menu action: copy label -void LelantusCoinControlDialog::copyLabel() -{ - if (ui->radioTreeMode->isChecked() && contextMenuItem->text(COLUMN_LABEL).length() == 0 && contextMenuItem->parent()) - GUIUtil::setClipboard(contextMenuItem->parent()->text(COLUMN_LABEL)); - else - GUIUtil::setClipboard(contextMenuItem->text(COLUMN_LABEL)); -} - -// context menu action: copy address -void LelantusCoinControlDialog::copyAddress() -{ - if (ui->radioTreeMode->isChecked() && contextMenuItem->text(COLUMN_ADDRESS).length() == 0 && contextMenuItem->parent()) - GUIUtil::setClipboard(contextMenuItem->parent()->text(COLUMN_ADDRESS)); - else - GUIUtil::setClipboard(contextMenuItem->text(COLUMN_ADDRESS)); -} - -// context menu action: copy transaction id -void LelantusCoinControlDialog::copyTransactionHash() -{ - GUIUtil::setClipboard(contextMenuItem->text(COLUMN_TXHASH)); -} - -// context menu action: lock coin -void LelantusCoinControlDialog::lockCoin() -{ - if (contextMenuItem->checkState(COLUMN_CHECKBOX) == Qt::Checked) - contextMenuItem->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); - - COutPoint outpt(uint256S(contextMenuItem->text(COLUMN_TXHASH).toStdString()), contextMenuItem->text(COLUMN_VOUT_INDEX).toUInt()); - model->lockCoin(outpt); - contextMenuItem->setDisabled(true); - contextMenuItem->setIcon(COLUMN_CHECKBOX, platformStyle->SingleColorIcon(":/icons/lock_closed")); - updateLabelLocked(); -} - -// context menu action: unlock coin -void LelantusCoinControlDialog::unlockCoin() -{ - COutPoint outpt(uint256S(contextMenuItem->text(COLUMN_TXHASH).toStdString()), contextMenuItem->text(COLUMN_VOUT_INDEX).toUInt()); - model->unlockCoin(outpt); - contextMenuItem->setDisabled(false); - contextMenuItem->setIcon(COLUMN_CHECKBOX, QIcon()); - updateLabelLocked(); -} - -// copy label "Quantity" to clipboard -void LelantusCoinControlDialog::clipboardQuantity() -{ - GUIUtil::setClipboard(ui->labelCoinControlQuantity->text()); -} - -// copy label "Amount" to clipboard -void LelantusCoinControlDialog::clipboardAmount() -{ - GUIUtil::setClipboard(ui->labelCoinControlAmount->text().left(ui->labelCoinControlAmount->text().indexOf(" "))); -} - -// copy label "Fee" to clipboard -void LelantusCoinControlDialog::clipboardFee() -{ - GUIUtil::setClipboard(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" ")).replace(ASYMP_UTF8, "")); -} - -// copy label "After fee" to clipboard -void LelantusCoinControlDialog::clipboardAfterFee() -{ - GUIUtil::setClipboard(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" ")).replace(ASYMP_UTF8, "")); -} - -// copy label "Bytes" to clipboard -void LelantusCoinControlDialog::clipboardBytes() -{ - GUIUtil::setClipboard(ui->labelCoinControlBytes->text().replace(ASYMP_UTF8, "")); -} - -// copy label "Dust" to clipboard -void LelantusCoinControlDialog::clipboardLowOutput() -{ - GUIUtil::setClipboard(ui->labelCoinControlLowOutput->text()); -} - -// copy label "Change" to clipboard -void LelantusCoinControlDialog::clipboardChange() -{ - GUIUtil::setClipboard(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" ")).replace(ASYMP_UTF8, "")); -} - -// treeview: sort -void LelantusCoinControlDialog::sortView(int column, Qt::SortOrder order) -{ - sortColumn = column; - sortOrder = order; - ui->treeWidget->sortItems(column, order); - ui->treeWidget->header()->setSortIndicator(sortColumn, sortOrder); -} - -// treeview: clicked on header -void LelantusCoinControlDialog::headerSectionClicked(int logicalIndex) -{ - if (logicalIndex == COLUMN_CHECKBOX) // click on most left column -> do nothing - { - ui->treeWidget->header()->setSortIndicator(sortColumn, sortOrder); - } - else - { - if (sortColumn == logicalIndex) - sortOrder = ((sortOrder == Qt::AscendingOrder) ? Qt::DescendingOrder : Qt::AscendingOrder); - else - { - sortColumn = logicalIndex; - sortOrder = ((sortColumn == COLUMN_LABEL || sortColumn == COLUMN_ADDRESS) ? Qt::AscendingOrder : Qt::DescendingOrder); // if label or address then default => asc, else default => desc - } - - sortView(sortColumn, sortOrder); - } -} - -// toggle tree mode -void LelantusCoinControlDialog::radioTreeMode(bool checked) -{ - if (checked && model) - updateView(); -} - -// toggle list mode -void LelantusCoinControlDialog::radioListMode(bool checked) -{ - if (checked && model) - updateView(); -} - -// checkbox clicked by user -void LelantusCoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column) -{ - if (column == COLUMN_CHECKBOX && item->text(COLUMN_TXHASH).length() == 64) // transaction hash is 64 characters (this means its a child node, so its not a parent node in tree mode) - { - COutPoint outpt(uint256S(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt()); - - if (item->checkState(COLUMN_CHECKBOX) == Qt::Unchecked) - storage->coinControl.UnSelect(outpt); - else if (item->isDisabled()) // locked (this happens if "check all" through parent node) - item->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); - else - storage->coinControl.Select(outpt); - - // selection changed -> update labels - if (ui->treeWidget->isEnabled()) // do not update on every click for (un)select all - storage->updateLabels(model, this); - } - - // TODO: Remove this temporary qt5 fix after Qt5.3 and Qt5.4 are no longer used. - // Fixed in Qt5.5 and above: https://bugreports.qt.io/browse/QTBUG-43473 -#if QT_VERSION >= 0x050000 - else if (column == COLUMN_CHECKBOX && item->childCount() > 0) - { - if (item->checkState(COLUMN_CHECKBOX) == Qt::PartiallyChecked && item->child(0)->checkState(COLUMN_CHECKBOX) == Qt::PartiallyChecked) - item->setCheckState(COLUMN_CHECKBOX, Qt::Checked); - } -#endif -} - -// shows count of locked unspent outputs -void LelantusCoinControlDialog::updateLabelLocked() -{ - std::vector vOutpts; - model->listLockedCoins(vOutpts); - if (vOutpts.size() > 0) - { - ui->labelLocked->setText(tr("(%1 locked)").arg(vOutpts.size())); - ui->labelLocked->setVisible(true); - } - else ui->labelLocked->setVisible(false); -} - - - -void LelantusCoinControlDialog::updateView() -{ - if (!model || !model->getOptionsModel() || !model->getAddressTableModel()) - return; - - bool treeMode = ui->radioTreeMode->isChecked(); - - ui->treeWidget->clear(); - ui->treeWidget->setEnabled(false); // performance, otherwise updateLabels would be called for every checked checkbox - ui->treeWidget->setAlternatingRowColors(!treeMode); - QFlags flgCheckbox = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable; - QFlags flgTristate = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate; - - int nDisplayUnit = model->getOptionsModel()->getDisplayUnit(); - - std::map > mapCoins; - model->listCoins(mapCoins, CoinType::ALL_COINS); - - BOOST_FOREACH(const PAIRTYPE(QString, std::vector)& coins, mapCoins) { - CCoinControlWidgetItem *itemWalletAddress = new CCoinControlWidgetItem(); - itemWalletAddress->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); - QString sWalletAddress = coins.first; - QString sWalletLabel = model->getAddressTableModel()->labelForAddress(sWalletAddress); - if (sWalletLabel.isEmpty()) - sWalletLabel = tr("(no label)"); - - if (treeMode) - { - // wallet address - ui->treeWidget->addTopLevelItem(itemWalletAddress); - - itemWalletAddress->setFlags(flgTristate); - itemWalletAddress->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); - - // label - itemWalletAddress->setText(COLUMN_LABEL, sWalletLabel); - - // address - itemWalletAddress->setText(COLUMN_ADDRESS, sWalletAddress); - } - - CAmount nSum = 0; - int nChildren = 0; - BOOST_FOREACH(const COutput& out, coins.second) { - nSum += out.tx->tx->vout[out.i].nValue; - nChildren++; - - CCoinControlWidgetItem *itemOutput; - if (treeMode) itemOutput = new CCoinControlWidgetItem(itemWalletAddress); - else itemOutput = new CCoinControlWidgetItem(ui->treeWidget); - itemOutput->setFlags(flgCheckbox); - itemOutput->setCheckState(COLUMN_CHECKBOX,Qt::Unchecked); - - // address - CTxDestination outputAddress; - QString sAddress = ""; - if(ExtractDestination(out.tx->tx->vout[out.i].scriptPubKey, outputAddress)) - { - sAddress = QString::fromStdString(CBitcoinAddress(outputAddress).ToString()); - - // if listMode or change => show Firo address. In tree mode, address is not shown again for direct wallet address outputs - if (!treeMode || (!(sAddress == sWalletAddress))) - itemOutput->setText(COLUMN_ADDRESS, sAddress); - } - - // label - if (!(sAddress == sWalletAddress)) // change - { - // tooltip from where the change comes from - itemOutput->setToolTip(COLUMN_LABEL, tr("change from %1 (%2)").arg(sWalletLabel).arg(sWalletAddress)); - itemOutput->setText(COLUMN_LABEL, tr("(change)")); - } - else if (!treeMode) - { - QString sLabel = model->getAddressTableModel()->labelForAddress(sAddress); - if (sLabel.isEmpty()) - sLabel = tr("(no label)"); - itemOutput->setText(COLUMN_LABEL, sLabel); - } - - // amount - itemOutput->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, out.tx->tx->vout[out.i].nValue)); - itemOutput->setData(COLUMN_AMOUNT, Qt::UserRole, QVariant((qlonglong)out.tx->tx->vout[out.i].nValue)); // padding so that sorting works correctly - - // date - itemOutput->setText(COLUMN_DATE, GUIUtil::dateTimeStr(out.tx->GetTxTime())); - itemOutput->setData(COLUMN_DATE, Qt::UserRole, QVariant((qlonglong)out.tx->GetTxTime())); - - // confirmations - itemOutput->setText(COLUMN_CONFIRMATIONS, QString::number(out.nDepth)); - itemOutput->setData(COLUMN_CONFIRMATIONS, Qt::UserRole, QVariant((qlonglong)out.nDepth)); - - // transaction hash - uint256 txhash = out.tx->tx->GetHash(); - itemOutput->setText(COLUMN_TXHASH, QString::fromStdString(txhash.GetHex())); - - // vout index - itemOutput->setText(COLUMN_VOUT_INDEX, QString::number(out.i)); - - // disable locked coins - if (model->isLockedCoin(txhash, out.i)) - { - COutPoint outpt(txhash, out.i); - storage->coinControl.UnSelect(outpt); // just to be sure - itemOutput->setDisabled(true); - itemOutput->setIcon(COLUMN_CHECKBOX, platformStyle->SingleColorIcon(":/icons/lock_closed")); - } - - // set checkbox - if (storage->coinControl.IsSelected(COutPoint(txhash, out.i))) - itemOutput->setCheckState(COLUMN_CHECKBOX, Qt::Checked); - } - - // amount - if (treeMode) - { - itemWalletAddress->setText(COLUMN_CHECKBOX, "(" + QString::number(nChildren) + ")"); - itemWalletAddress->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, nSum)); - itemWalletAddress->setData(COLUMN_AMOUNT, Qt::UserRole, QVariant((qlonglong)nSum)); - } - } - - // expand all partially selected - if (treeMode) - { - for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) - if (ui->treeWidget->topLevelItem(i)->checkState(COLUMN_CHECKBOX) == Qt::PartiallyChecked) - ui->treeWidget->topLevelItem(i)->setExpanded(true); - } - - // sort view - sortView(sortColumn, sortOrder); - ui->treeWidget->setEnabled(true); -} diff --git a/src/qt/lelantuscoincontroldialog.h b/src/qt/lelantuscoincontroldialog.h deleted file mode 100644 index 53c4589856..0000000000 --- a/src/qt/lelantuscoincontroldialog.h +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2020 The Firo Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef FIRO_QT_LELANTUSCOINCONTROLDIALOG_H -#define FIRO_QT_LELANTUSCOINCONTROLDIALOG_H - -#include "../amount.h" -#include "../script/standard.h" -#include "../wallet/coincontrol.h" - -#include "walletmodel.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#define ASYMP_UTF8 "\xE2\x89\x88" - -class CoinControlStorage : public QObject -{ - Q_OBJECT -public: - CoinControlStorage(); - -public: - QList payAmounts; - CCoinControl coinControl; - bool fSubtractFeeFromAmount; - -public: - void updateLabels(WalletModel*, QDialog*); -}; - -namespace Ui -{ - class CoinControlDialog; -} - -class LelantusCoinControlDialog : public QDialog -{ - Q_OBJECT - -public: - explicit LelantusCoinControlDialog( - CoinControlStorage *storage, - const PlatformStyle *platformStyle, - QWidget *parent = 0); - ~LelantusCoinControlDialog(); - - void setModel(WalletModel *model); - - CoinControlStorage *storage; - -private: - Ui::CoinControlDialog *ui; - WalletModel *model; - int sortColumn; - Qt::SortOrder sortOrder; - - QMenu *contextMenu; - QTreeWidgetItem *contextMenuItem; - QAction *copyTransactionHashAction; - QAction *lockAction; - QAction *unlockAction; - - const PlatformStyle *platformStyle; - - void sortView(int, Qt::SortOrder); - void updateView(); - - enum - { - COLUMN_CHECKBOX = 0, - COLUMN_AMOUNT, - COLUMN_LABEL, - COLUMN_ADDRESS, - COLUMN_DATE, - COLUMN_CONFIRMATIONS, - COLUMN_TXHASH, - COLUMN_VOUT_INDEX, - }; - friend class CCoinControlWidgetItem; - -private Q_SLOTS: - void showMenu(const QPoint &); - void copyAmount(); - void copyLabel(); - void copyAddress(); - void copyTransactionHash(); - void lockCoin(); - void unlockCoin(); - void clipboardQuantity(); - void clipboardAmount(); - void clipboardFee(); - void clipboardAfterFee(); - void clipboardBytes(); - void clipboardLowOutput(); - void clipboardChange(); - void radioTreeMode(bool); - void radioListMode(bool); - void viewItemChanged(QTreeWidgetItem*, int); - void headerSectionClicked(int); - void buttonBoxClicked(QAbstractButton*); - void buttonSelectAllClicked(); - void updateLabelLocked(); -}; - -#endif // FIRO_QT_LELANTUSCOINCONTROLDIALOG_H diff --git a/src/qt/lelantusdialog.cpp b/src/qt/lelantusdialog.cpp deleted file mode 100644 index be6e2ef2b2..0000000000 --- a/src/qt/lelantusdialog.cpp +++ /dev/null @@ -1,763 +0,0 @@ -#include "../lelantus.h" -#include "../script/standard.h" -#include "../validation.h" -#include "../wallet/coincontrol.h" - -#include "addresstablemodel.h" -#include "bitcoinunits.h" -#include "guiutil.h" -#include "optionsmodel.h" -#include "ui_lelantusdialog.h" -#include "lelantusdialog.h" -#include "lelantusmodel.h" -#include "sendcoinsdialog.h" -#include "walletmodel.h" - -#include - -#define SEND_CONFIRM_DELAY 3 - -LelantusDialog::LelantusDialog(const PlatformStyle *platformStyle, QWidget *parent) : - QDialog(parent), - ui(new Ui::LelantusDialog), - clientModel(0), - walletModel(0), - platformStyle(platformStyle), - cachedPrivateBalance(0), - cachedUnconfirmedPrivateBalance(0), - cachedAnonymizableBalance(0), - currentUnit(BitcoinUnits::Unit::BTC) -{ - ui->setupUi(this); - setWindowTitle(tr("Lelantus")); - - // hide amount of global pool - // ui->globalTotalCoinsAmount->setVisible(false); - // ui->globalLatestGroupCoinsAmount->setVisible(false); - // ui->globalUnspentAmount->setVisible(false); - - // Coin Control - connect(ui->pushButtonCoinControl, &QPushButton::clicked, this, &LelantusDialog::coinControlButtonClicked); - connect(ui->checkBoxCoinControlChange, &QCheckBox::stateChanged, this, &LelantusDialog::coinControlChangeChecked); - connect(ui->lineEditCoinControlChange, &QValidatedLineEdit::textEdited, this, &LelantusDialog::coinControlChangeEdited); - - // Coin Control: clipboard actions - QAction *clipboardQuantityAction = new QAction(tr("Copy quantity"), this); - QAction *clipboardAmountAction = new QAction(tr("Copy amount"), this); - QAction *clipboardFeeAction = new QAction(tr("Copy fee"), this); - QAction *clipboardAfterFeeAction = new QAction(tr("Copy after fee"), this); - QAction *clipboardBytesAction = new QAction(tr("Copy bytes"), this); - QAction *clipboardLowOutputAction = new QAction(tr("Copy dust"), this); - QAction *clipboardChangeAction = new QAction(tr("Copy change"), this); - connect(clipboardQuantityAction, &QAction::triggered, this, &LelantusDialog::coinControlClipboardQuantity); - connect(clipboardAmountAction, &QAction::triggered, this, &LelantusDialog::coinControlClipboardAmount); - connect(clipboardFeeAction, &QAction::triggered, this, &LelantusDialog::coinControlClipboardFee); - connect(clipboardAfterFeeAction, &QAction::triggered, this, &LelantusDialog::coinControlClipboardAfterFee); - connect(clipboardBytesAction, &QAction::triggered, this, &LelantusDialog::coinControlClipboardBytes); - connect(clipboardLowOutputAction, &QAction::triggered, this, &LelantusDialog::coinControlClipboardLowOutput); - connect(clipboardChangeAction, &QAction::triggered, this, &LelantusDialog::coinControlClipboardChange); - - // init transaction fee section. - QSettings settings; - if (!settings.contains("lelantus::fFeeSectionMinimized")) - settings.setValue("lelantus::fFeeSectionMinimized", true); - - if (!settings.contains("lelantus::nFeeRadio") - && settings.contains("lelantus::nTransactionFee") - && settings.value("lelantus::nTransactionFee").toLongLong() > 0) // compatibility - settings.setValue("lelantus::nFeeRadio", 1); // custom - - if (!settings.contains("lelantus::nFeeRadio")) - settings.setValue("lelantus::nFeeRadio", 0); // recommended - - if (!settings.contains("lelantus::nCustomFeeRadio") - && settings.contains("lelantus::nTransactionFee") - && settings.value("lelantus::nTransactionFee").toLongLong() > 0) // compatibility - settings.setValue("lelantus::nCustomFeeRadio", 1); // total at least - - if (!settings.contains("lelantus::nCustomFeeRadio")) - settings.setValue("lelantus::nCustomFeeRadio", 0); // per kilobyte - - if (!settings.contains("lelantus::nTransactionFee")) - settings.setValue("lelantus::nTransactionFee", - (qint64)DEFAULT_TRANSACTION_FEE); - - if (!settings.contains("lelantus::fPayOnlyMinFee")) - settings.setValue("lelantus::fPayOnlyMinFee", false); - - ui->groupCustomFee->setId(ui->radioCustomPerKilobyte, 0); - ui->groupCustomFee->setId(ui->radioCustomAtLeast, 1); - ui->groupCustomFee->button((int)std::max(0, std::min(1, settings.value("lelantus::nCustomFeeRadio").toInt())))->setChecked(true); - ui->customFee->setValue(settings.value("lelantus::nTransactionFee").toLongLong()); - ui->checkBoxMinimumFee->setChecked(settings.value("lelantus::fPayOnlyMinFee").toBool()); - minimizeFeeSection(settings.value("lelantus::fFeeSectionMinimized").toBool()); -} - -LelantusDialog::~LelantusDialog() -{ - QSettings settings; - settings.setValue("lelantus::fFeeSectionMinimized", fFeeMinimized); - settings.setValue("lelantus::nFeeRadio", true); - settings.setValue("lelantus::nCustomFeeRadio", ui->groupCustomFee->checkedId()); - settings.setValue("lelantus::nSmartFeeSliderPosition", ui->sliderSmartFee->value()); - settings.setValue("lelantus::nTransactionFee", (qint64)ui->customFee->value()); - settings.setValue("lelantus::fPayOnlyMinFee", ui->checkBoxMinimumFee->isChecked()); - - delete ui; -} - -void LelantusDialog::setClientModel(ClientModel *_clientModel) -{ - this->clientModel = _clientModel; - - if (_clientModel) { - connect(_clientModel, &ClientModel::numBlocksChanged, this, &LelantusDialog::updateSmartFeeLabel); - connect(_clientModel, &ClientModel::numBlocksChanged, this, &LelantusDialog::updateGlobalState); - } -} - -void LelantusDialog::setWalletModel(WalletModel *_walletModel) -{ - this->walletModel = _walletModel; - - if (_walletModel) { - connect(_walletModel, &WalletModel::balanceChanged, this, &LelantusDialog::setBalance); - connect(_walletModel->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &LelantusDialog::updateDisplayUnit); - - auto privateBalance = _walletModel->getLelantusModel()->getPrivateBalance(); - setBalance(0, 0, 0, 0, 0, 0, - privateBalance.first, - privateBalance.second, - _walletModel->getAnonymizableBalance()); - - // Coin Control - connect(_walletModel->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &LelantusDialog::coinControlUpdateLabels); - connect(_walletModel->getOptionsModel(), &OptionsModel::coinControlFeaturesChanged, this, &LelantusDialog::coinControlFeatureChanged); - ui->frameCoinControl->setVisible( - _walletModel->getOptionsModel()->getCoinControlFeatures()); - coinControlUpdateLabels(); - - auto unit = _walletModel->getOptionsModel()->getDisplayUnit(); - currentUnit = unit; - updateDisplayUnit(unit); - - // fee section - connect(ui->sliderSmartFee, &QSlider::valueChanged, this, &LelantusDialog::updateSmartFeeLabel); - connect(ui->sliderSmartFee, &QSlider::valueChanged, this, &LelantusDialog::updateGlobalFeeVariables); - connect(ui->sliderSmartFee, &QSlider::valueChanged, this, &LelantusDialog::coinControlUpdateLabels); - connect(ui->groupFee, qOverload(&QButtonGroup::buttonClicked), this, &LelantusDialog::updateFeeSectionControls); - connect(ui->groupFee, qOverload(&QButtonGroup::buttonClicked), this, &LelantusDialog::updateGlobalFeeVariables); - connect(ui->groupFee, qOverload(&QButtonGroup::buttonClicked), this, &LelantusDialog::coinControlUpdateLabels); - connect(ui->groupCustomFee, qOverload(&QButtonGroup::buttonClicked), this, &LelantusDialog::updateGlobalFeeVariables); - connect(ui->groupCustomFee, qOverload(&QButtonGroup::buttonClicked), this, &LelantusDialog::coinControlUpdateLabels); - connect(ui->customFee, &BitcoinAmountField::valueChanged, this, &LelantusDialog::updateGlobalFeeVariables); - connect(ui->customFee, &BitcoinAmountField::valueChanged, this, &LelantusDialog::coinControlUpdateLabels); - connect(ui->checkBoxMinimumFee, &QCheckBox::stateChanged, this, &LelantusDialog::setMinimumFee); - connect(ui->checkBoxMinimumFee, &QCheckBox::stateChanged, this, &LelantusDialog::updateFeeSectionControls); - connect(ui->checkBoxMinimumFee, &QCheckBox::stateChanged, this, &LelantusDialog::updateGlobalFeeVariables); - connect(ui->checkBoxMinimumFee, &QCheckBox::stateChanged, this, &LelantusDialog::coinControlUpdateLabels); - ui->customFee->setSingleStep(CWallet::GetRequiredFee(1000)); - updateFeeSectionControls(); - updateMinFeeLabel(); - updateSmartFeeLabel(); - updateGlobalFeeVariables(); - - // set the smartfee-sliders default value (wallets default conf.target or last stored value) - QSettings settings; - if (settings.value("lelantus::nSmartFeeSliderPosition").toInt() == 0) - { - ui->sliderSmartFee->setValue(ui->sliderSmartFee->maximum() - - walletModel->getDefaultConfirmTarget() + 2); - } - else - { - ui->sliderSmartFee->setValue( - settings.value("lelantus::nSmartFeeSliderPosition").toInt()); - } - } -} - -void LelantusDialog::clear() -{ - ui->anonymizeAmount->setValue(0); -} - -void LelantusDialog::accept() -{ - clear(); -} - -void LelantusDialog::setBalance( - const CAmount& balance, - const CAmount& unconfirmedBalance, - const CAmount& immatureBalance, - const CAmount& watchOnlyBalance, - const CAmount& watchUnconfBalance, - const CAmount& watchImmatureBalance, - const CAmount& privateBalance, - const CAmount& unconfirmedPrivateBalance, - const CAmount& anonymizableBalance) -{ - if (cachedPrivateBalance != privateBalance - || cachedUnconfirmedPrivateBalance != unconfirmedPrivateBalance - || cachedAnonymizableBalance != anonymizableBalance) - { - cachedPrivateBalance = privateBalance; - cachedUnconfirmedPrivateBalance = unconfirmedPrivateBalance; - cachedAnonymizableBalance = anonymizableBalance; - - updateBalanceDisplay(); - } -} - -void LelantusDialog::updateDisplayUnit(int unit) -{ - ui->anonymizeUnit->setText(BitcoinUnits::name(unit)); - - if(walletModel && walletModel->getOptionsModel()) { - ui->anonymizeAmount->setDisplayUnit(walletModel->getOptionsModel()->getDisplayUnit()); - } - - updateBalanceDisplay(unit); - updateGlobalState(); - - updateMinFeeLabel(); - updateSmartFeeLabel(); - - currentUnit = unit; -} - -void LelantusDialog::updateGlobalState() -{ - auto state = lelantus::CLelantusState::GetState(); - auto mintCount = state->GetMints().size(); - auto spendCount = state->GetSpends().size(); - size_t mintsInLatestGroup = 0; - - if (mintCount) { - lelantus::CLelantusState::LelantusCoinGroupInfo group; - if (state->GetCoinGroupInfo(state->GetLatestCoinID(), group)) { - mintsInLatestGroup = group.nCoins; - } - } - - ui->globalTotalCoins->setText(QString::fromStdString(std::to_string(mintCount))); - ui->globalLatestGroupCoins->setText(QString::fromStdString(std::to_string(mintsInLatestGroup))); - ui->globalUnspent->setText(QString::fromStdString(std::to_string(mintCount - spendCount))); -} - -void LelantusDialog::on_anonymizeButton_clicked() -{ - updateGlobalFeeVariables(); - - CAmount val = ui->anonymizeAmount->value(); - - if (val < 0 || val > BitcoinUnits::maxMoney()) { - val = 0; - } - - WalletModel::UnlockContext ctx(walletModel->requestUnlock()); - if (!ctx.isValid()) - { - // Unlock wallet was cancelled - return; - } - - std::vector wtxs; - std::list reserveKeys; - std::vector mints; - - CCoinControl ctrl; - if (walletModel->getOptionsModel()->getCoinControlFeatures()) { - ctrl = coinControlStorage.coinControl; - removeUnmatchedOutput(ctrl); - } - - auto coinControl = coinControlStorage.coinControl; - auto prepareStatus = walletModel->prepareMintTransactions( - val, - wtxs, - reserveKeys, - mints, - &ctrl); - - CAmount allAmount = 0; - CAmount allFee = 0; - unsigned int allTxSize = 0; - for (auto &wtx : wtxs) { - allAmount += wtx.getTotalTransactionAmount(); - allFee += wtx.getTransactionFee(); - allTxSize += wtx.getTransactionSize(); - } - - processSendCoinsReturn( - prepareStatus, - BitcoinUnits::formatWithUnit( - walletModel->getOptionsModel()->getDisplayUnit(), - allFee) - ); - - if (prepareStatus.status != WalletModel::OK) { - return; - } - - QStringList formatted; - - QString questionString = tr("Are you sure you want to anonymize %1?") - .arg(BitcoinUnits::formatWithUnit( - walletModel->getOptionsModel()->getDisplayUnit(), - allAmount, - false, - BitcoinUnits::separatorAlways - )); - - questionString.append("

%1"); - - if (allFee > 0) { - // append fee string if a fee is required - questionString.append("
"); - questionString.append(BitcoinUnits::formatHtmlWithUnit(walletModel->getOptionsModel()->getDisplayUnit(), allFee)); - questionString.append(" "); - questionString.append(tr("added as transaction fee")); - - // append transaction size - questionString.append(" (" + QString::number((double)allTxSize / 1000) + " kB)"); - } - - // add total amount in all subdivision units - questionString.append("
"); - CAmount totalAmount = allAmount + allFee; - QStringList alternativeUnits; - for (auto u : BitcoinUnits::availableUnits()) { - if(u != walletModel->getOptionsModel()->getDisplayUnit()) { - alternativeUnits.append(BitcoinUnits::formatHtmlWithUnit(u, totalAmount)); - } - } - - questionString.append(tr("Total Amount %1") - .arg(BitcoinUnits::formatHtmlWithUnit(walletModel->getOptionsModel()->getDisplayUnit(), totalAmount))); - questionString.append(QString("
(=%2)
") - .arg(alternativeUnits.join(" " + tr("or") + "
"))); - - SendConfirmationDialog confirmationDialog(tr("Confirm anonymize coins"), - questionString.arg(formatted.join("
")), SEND_CONFIRM_DELAY, this); - - confirmationDialog.exec(); - QMessageBox::StandardButton retval = (QMessageBox::StandardButton)confirmationDialog.result(); - - if (retval != QMessageBox::Yes) - { - return; - } - - auto sendStatus = walletModel->sendAnonymizingCoins(wtxs, reserveKeys, mints); - - processSendCoinsReturn(sendStatus); - - if (sendStatus.status == WalletModel::OK) { - accept(); - coinControlStorage.coinControl.UnSelectAll(); - coinControlUpdateLabels(); - ui->anonymizeAmount->clear(); - } -} - -void LelantusDialog::updateBalanceDisplay(int unit) -{ - if (unit == -1) { - if (walletModel && walletModel->getOptionsModel()) { - unit = walletModel->getOptionsModel()->getDisplayUnit(); - } else { - unit = BitcoinUnits::Unit::BTC; - } - } - - size_t confirmeds, unconfirmeds; - std::tie(cachedPrivateBalance, cachedUnconfirmedPrivateBalance) = walletModel->getLelantusModel()->getPrivateBalance(confirmeds, unconfirmeds); - - auto totalCoins = confirmeds + unconfirmeds; - auto totalAmount = cachedPrivateBalance + cachedUnconfirmedPrivateBalance; - - // set available amount - auto avaiableAmountToAnonymizeText = tr("Available amount to anonymize %1") - .arg(BitcoinUnits::formatWithUnit(unit, cachedAnonymizableBalance, false, BitcoinUnits::separatorAlways)); - ui->availableAmounToAnonymize->setText(avaiableAmountToAnonymizeText); - - // set coins count - ui->spendable->setText(QString::fromStdString(std::to_string(confirmeds))); - ui->unconfirmed->setText(QString::fromStdString(std::to_string(unconfirmeds))); - ui->total->setText(QString::fromStdString(std::to_string(totalCoins))); - - // set amount - ui->spendableAmount->setText(BitcoinUnits::formatWithUnit( - unit, cachedPrivateBalance, false, BitcoinUnits::separatorAlways)); - ui->unconfirmedAmount->setText(BitcoinUnits::formatWithUnit( - unit, cachedUnconfirmedPrivateBalance, false, BitcoinUnits::separatorAlways)); - ui->totalAmount->setText(BitcoinUnits::formatWithUnit( - unit, totalAmount, false, BitcoinUnits::separatorAlways)); -} - -void LelantusDialog::processSendCoinsReturn( - const WalletModel::SendCoinsReturn &sendCoinsReturn, - const QString &msgArg) -{ - QPair msgParams; - msgParams.second = CClientUIInterface::MSG_WARNING; - - switch (sendCoinsReturn.status) - { - case WalletModel::InvalidAmount: - msgParams.first = tr("The amount to pay must be larger than 0."); - break; - case WalletModel::AmountExceedsBalance: - msgParams.first = tr("The amount exceeds your balance."); - break; - case WalletModel::AmountWithFeeExceedsBalance: - msgParams.first = tr("The total exceeds your balance when the %1 transaction fee is included.").arg(msgArg); - break; - case WalletModel::TransactionCreationFailed: - msgParams.first = tr("Transaction creation failed!"); - msgParams.second = CClientUIInterface::MSG_ERROR; - break; - case WalletModel::TransactionCommitFailed: - msgParams.first = tr("The transaction was rejected with the following reason: %1").arg(sendCoinsReturn.reasonCommitFailed); - msgParams.second = CClientUIInterface::MSG_ERROR; - break; - case WalletModel::AbsurdFee: - msgParams.first = tr("A fee higher than %1 is considered an absurdly high fee.").arg(BitcoinUnits::formatWithUnit(walletModel->getOptionsModel()->getDisplayUnit(), maxTxFee)); - break; - case WalletModel::OK: - default: - return; - } - - Q_EMIT message(tr("Anonymize Coins"), msgParams.first, msgParams.second); -} - -void LelantusDialog::minimizeFeeSection(bool fMinimize) -{ - ui->labelFeeMinimized->setVisible(fMinimize); - ui->buttonChooseFee ->setVisible(fMinimize); - ui->buttonMinimizeFee->setVisible(!fMinimize); - ui->frameFeeSelection->setVisible(!fMinimize); - ui->horizontalLayoutSmartFee->setContentsMargins(0, (fMinimize ? 0 : 6), 0, 0); - fFeeMinimized = fMinimize; -} - -void LelantusDialog::on_buttonChooseFee_clicked() -{ - minimizeFeeSection(false); -} - -void LelantusDialog::on_buttonMinimizeFee_clicked() -{ - updateFeeMinimizedLabel(); - minimizeFeeSection(true); -} - -void LelantusDialog::setMinimumFee() -{ - ui->radioCustomPerKilobyte->setChecked(true); - ui->customFee->setValue(CWallet::GetRequiredFee(1000)); -} - -void LelantusDialog::updateFeeSectionControls() -{ - ui->sliderSmartFee ->setEnabled(ui->radioSmartFee->isChecked()); - ui->labelSmartFee ->setEnabled(ui->radioSmartFee->isChecked()); - ui->labelSmartFee2 ->setEnabled(ui->radioSmartFee->isChecked()); - ui->labelSmartFee3 ->setEnabled(ui->radioSmartFee->isChecked()); - ui->labelFeeEstimation ->setEnabled(ui->radioSmartFee->isChecked()); - ui->labelSmartFeeNormal ->setEnabled(ui->radioSmartFee->isChecked()); - ui->labelSmartFeeFast ->setEnabled(ui->radioSmartFee->isChecked()); - - ui->confirmationTargetLabel ->setEnabled(ui->radioSmartFee->isChecked()); - ui->checkBoxMinimumFee ->setEnabled(ui->radioCustomFee->isChecked()); - ui->labelMinFeeWarning ->setEnabled(ui->radioCustomFee->isChecked()); - ui->radioCustomPerKilobyte ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked()); - ui->radioCustomAtLeast ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked() && coinControlStorage.coinControl.HasSelected()); - ui->customFee ->setEnabled(ui->radioCustomFee->isChecked() && !ui->checkBoxMinimumFee->isChecked()); -} - -void LelantusDialog::updateGlobalFeeVariables() -{ - auto &coinControl = coinControlStorage.coinControl; - if (ui->radioSmartFee->isChecked()) - { - int nConfirmTarget = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; - payTxFee = CFeeRate(0); - - // set nMinimumTotalFee to 0 to not accidentally pay a custom fee - coinControl.nMinimumTotalFee = 0; - - // show the estimated required time for confirmation - ui->confirmationTargetLabel->setText( - GUIUtil::formatDurationStr(nConfirmTarget * Params().GetConsensus().nPowTargetSpacing) - + " / " + tr("%n block(s)", "", nConfirmTarget)); - } - else - { - payTxFee = CFeeRate(ui->customFee->value()); - - // if user has selected to set a minimum absolute fee, pass the value to coincontrol - // set nMinimumTotalFee to 0 in case of user has selected that the fee is per KB - coinControl.nMinimumTotalFee = ui->radioCustomAtLeast->isChecked() ? ui->customFee->value() : 0; - } -} - -void LelantusDialog::updateFeeMinimizedLabel() -{ - if(!walletModel || !walletModel->getOptionsModel()) - return; - if (ui->radioSmartFee->isChecked()) - ui->labelFeeMinimized->setText(ui->labelSmartFee->text()); - else { - ui->labelFeeMinimized->setText(BitcoinUnits::formatWithUnit(walletModel->getOptionsModel()->getDisplayUnit(), ui->customFee->value()) + - ((ui->radioCustomPerKilobyte->isChecked()) ? "/kB" : "")); - } -} - -CAmount LelantusDialog::getAmount(int unit) -{ - return ui->anonymizeAmount->value(); -} - -void LelantusDialog::removeUnmatchedOutput(CCoinControl &coinControl) -{ - std::vector outpoints; - coinControl.ListSelected(outpoints); - - for (auto const &out : outpoints) { - auto it = pwalletMain->mapWallet.find(out.hash); - if (it == pwalletMain->mapWallet.end()) { - coinControl.UnSelect(out); - continue; - } - } -} - -void LelantusDialog::updateMinFeeLabel() -{ - if (walletModel && walletModel->getOptionsModel()) - ui->checkBoxMinimumFee->setText(tr("Pay only the required fee of %1").arg( - BitcoinUnits::formatWithUnit(walletModel->getOptionsModel()->getDisplayUnit(), CWallet::GetRequiredFee(1000)) + "/kB") - ); -} - -void LelantusDialog::updateSmartFeeLabel() -{ - if(!walletModel || !walletModel->getOptionsModel()) - return; - - int nBlocksToConfirm = ui->sliderSmartFee->maximum() - ui->sliderSmartFee->value() + 2; - int estimateFoundAtBlocks = nBlocksToConfirm; - CFeeRate feeRate = mempool.estimateSmartFee(nBlocksToConfirm, &estimateFoundAtBlocks); - if (feeRate <= CFeeRate(0)) // not enough data => minfee - { - ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit( - walletModel->getOptionsModel()->getDisplayUnit(), - std::max(CWallet::fallbackFee.GetFeePerK(), CWallet::GetRequiredFee(1000))) + "/kB"); - ui->labelSmartFee2->show(); // (Smart fee not initialized yet. This usually takes a few blocks...) - ui->labelFeeEstimation->setText(""); - ui->fallbackFeeWarningLabel->setVisible(true); - int lightness = ui->fallbackFeeWarningLabel->palette().color(QPalette::WindowText).lightness(); - QColor warning_colour(255 - (lightness / 5), 176 - (lightness / 3), 48 - (lightness / 14)); - ui->fallbackFeeWarningLabel->setStyleSheet("QLabel { color: " + warning_colour.name() + "; }"); - ui->fallbackFeeWarningLabel->setIndent(QFontMetrics(ui->fallbackFeeWarningLabel->font()).width("x")); - } - else - { - ui->labelSmartFee->setText(BitcoinUnits::formatWithUnit( - walletModel->getOptionsModel()->getDisplayUnit(), - std::max(feeRate.GetFeePerK(), CWallet::GetRequiredFee(1000))) + "/kB"); - ui->labelSmartFee2->hide(); - ui->labelFeeEstimation->setText(tr("Estimated to begin confirmation within %n block(s).", "", estimateFoundAtBlocks)); - ui->fallbackFeeWarningLabel->setVisible(false); - } - - updateFeeMinimizedLabel(); -} - -// coin controls -void LelantusDialog::coinControlFeatureChanged(bool checked) -{ - ui->frameCoinControl->setVisible(checked); - - if (!checked && walletModel) { - coinControlStorage.coinControl.SetNull(); - } - - // make sure we set back the confirmation target - updateGlobalFeeVariables(); - coinControlUpdateLabels(); -} - -// Coin Control: button inputs -> show actual coin control dialog -void LelantusDialog::coinControlButtonClicked() -{ - LelantusCoinControlDialog dlg(&coinControlStorage, platformStyle); - dlg.setModel(walletModel); - dlg.exec(); - - coinControlUpdateLabels(); -} - -// Coin Control: checkbox custom change address -void LelantusDialog::coinControlChangeChecked(int state) -{ - if (state == Qt::Unchecked) { - coinControlStorage.coinControl.destChange = CNoDestination(); - ui->labelCoinControlChangeLabel->clear(); - } else { - // use this to re-validate an already entered address - coinControlChangeEdited(ui->lineEditCoinControlChange->text()); - } - - ui->lineEditCoinControlChange->setEnabled((state == Qt::Checked)); -} - -// Coin Control: custom change address changed -void LelantusDialog::coinControlChangeEdited(const QString& text) -{ - if (walletModel && walletModel->getAddressTableModel()) { - // Default to no change address until verified - coinControlStorage.coinControl.destChange = CNoDestination(); - ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:red;}"); - - CBitcoinAddress addr = CBitcoinAddress(text.toStdString()); - - if (text.isEmpty()) // Nothing entered - { - ui->labelCoinControlChangeLabel->setText(""); - } - else if (!addr.IsValid()) // Invalid address - { - ui->labelCoinControlChangeLabel->setText(tr("Warning: Invalid Firo address")); - } - else // Valid address - { - CKeyID keyid; - addr.GetKeyID(keyid); - if (!walletModel->havePrivKey(keyid)) // Unknown change address - { - ui->labelCoinControlChangeLabel->setText(tr("Warning: Unknown change address")); - - // confirmation dialog - QMessageBox::StandardButton btnRetVal = QMessageBox::question(this, tr("Confirm custom change address"), tr("The address you selected for change is not part of this wallet. Any or all funds in your wallet may be sent to this address. Are you sure?"), - QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel); - - if(btnRetVal == QMessageBox::Yes) - coinControlStorage.coinControl.destChange = addr.Get(); - else - { - ui->lineEditCoinControlChange->setText(""); - ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:black;}"); - ui->labelCoinControlChangeLabel->setText(""); - } - } - else // Known change address - { - ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:black;}"); - - // Query label - QString associatedLabel = walletModel - ->getAddressTableModel() - ->labelForAddress(text); - - if (!associatedLabel.isEmpty()) - ui->labelCoinControlChangeLabel->setText(associatedLabel); - else - ui->labelCoinControlChangeLabel->setText(tr("(no label)")); - - coinControlStorage.coinControl.destChange = addr.Get(); - } - } - } -} - -// Coin Control: update labels -void LelantusDialog::coinControlUpdateLabels() -{ - if (!walletModel || !walletModel->getOptionsModel()) - return; - - if (walletModel->getOptionsModel()->getCoinControlFeatures()) - { - // enable minimum absolute fee UI controls - ui->radioCustomAtLeast->setVisible(true); - - // only enable the feature if inputs are selected - ui->radioCustomAtLeast->setEnabled(ui->radioCustomFee->isChecked() - && !ui->checkBoxMinimumFee->isChecked() - && coinControlStorage.coinControl.HasSelected()); - } - else - { - // in case coin control is disabled (=default), hide minimum absolute fee UI controls - ui->radioCustomAtLeast->setVisible(false); - return; - } - - // set pay amounts - coinControlStorage.payAmounts = {getAmount()}; - coinControlStorage.fSubtractFeeFromAmount = false; - - if (coinControlStorage.coinControl.HasSelected()) - { - // actual coin control calculation - coinControlStorage.updateLabels(walletModel, this); - - // show coin control stats - ui->labelCoinControlAutomaticallySelected->hide(); - ui->widgetCoinControl->show(); - } - else - { - // hide coin control stats - ui->labelCoinControlAutomaticallySelected->show(); - ui->widgetCoinControl->hide(); - ui->labelCoinControlInsuffFunds->hide(); - } -} - -// Coin Control: copy label "Quantity" to clipboard -void LelantusDialog::coinControlClipboardQuantity() -{ - GUIUtil::setClipboard(ui->labelCoinControlQuantity->text()); -} - -// Coin Control: copy label "Amount" to clipboard -void LelantusDialog::coinControlClipboardAmount() -{ - GUIUtil::setClipboard(ui->labelCoinControlAmount->text().left(ui->labelCoinControlAmount->text().indexOf(" "))); -} - -// Coin Control: copy label "Fee" to clipboard -void LelantusDialog::coinControlClipboardFee() -{ - GUIUtil::setClipboard(ui->labelCoinControlFee->text().left(ui->labelCoinControlFee->text().indexOf(" ")).replace(ASYMP_UTF8, "")); -} - -// Coin Control: copy label "After fee" to clipboard -void LelantusDialog::coinControlClipboardAfterFee() -{ - GUIUtil::setClipboard(ui->labelCoinControlAfterFee->text().left(ui->labelCoinControlAfterFee->text().indexOf(" ")).replace(ASYMP_UTF8, "")); -} - -// Coin Control: copy label "Bytes" to clipboard -void LelantusDialog::coinControlClipboardBytes() -{ - GUIUtil::setClipboard(ui->labelCoinControlBytes->text().replace(ASYMP_UTF8, "")); -} - -// Coin Control: copy label "Dust" to clipboard -void LelantusDialog::coinControlClipboardLowOutput() -{ - GUIUtil::setClipboard(ui->labelCoinControlLowOutput->text()); -} - -// Coin Control: copy label "Change" to clipboard -void LelantusDialog::coinControlClipboardChange() -{ - GUIUtil::setClipboard(ui->labelCoinControlChange->text().left(ui->labelCoinControlChange->text().indexOf(" ")).replace(ASYMP_UTF8, "")); -} \ No newline at end of file diff --git a/src/qt/lelantusdialog.h b/src/qt/lelantusdialog.h deleted file mode 100644 index d837a5df16..0000000000 --- a/src/qt/lelantusdialog.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef FIRO_QT_LELANTUSDIALOG_H -#define FIRO_QT_LELANTUSDIALOG_H - -#include "../script/standard.h" -#include "../wallet/coincontrol.h" - -#include "clientmodel.h" -#include "platformstyle.h" -#include "lelantuscoincontroldialog.h" -#include "walletmodel.h" - -#include -#include - -namespace Ui { - class LelantusDialog; -} - -class LelantusDialog : public QDialog -{ - Q_OBJECT - -public: - LelantusDialog(const PlatformStyle *platformStyle, QWidget *parent = 0); - ~LelantusDialog(); - - void setClientModel(ClientModel *model); - void setWalletModel(WalletModel *model); - -Q_SIGNALS: - // Fired when a message should be reported to the user - void message(const QString &title, const QString &message, unsigned int style); - -public Q_SLOTS: - void clear(); - void accept(); - - void setBalance( - const CAmount& balance, - const CAmount& unconfirmedBalance, - const CAmount& immatureBalance, - const CAmount& watchOnlyBalance, - const CAmount& watchUnconfBalance, - const CAmount& watchImmatureBalance, - const CAmount& privateBalance, - const CAmount& unconfirmedPrivateBalance, - const CAmount& anonymizableBalance); - - void updateDisplayUnit(int unit); - void updateGlobalState(); - -private Q_SLOTS: - void on_anonymizeButton_clicked(); - void on_buttonChooseFee_clicked(); - void on_buttonMinimizeFee_clicked(); - void coinControlFeatureChanged(bool); - void coinControlButtonClicked(); - void coinControlChangeChecked(int); - void coinControlChangeEdited(const QString &); - void coinControlUpdateLabels(); - void coinControlClipboardQuantity(); - void coinControlClipboardAmount(); - void coinControlClipboardFee(); - void coinControlClipboardAfterFee(); - void coinControlClipboardBytes(); - void coinControlClipboardLowOutput(); - void coinControlClipboardChange(); - void setMinimumFee(); - void updateFeeSectionControls(); - void updateMinFeeLabel(); - void updateSmartFeeLabel(); - void updateGlobalFeeVariables(); - -private: - void updateBalanceDisplay(int unit = -1); - void processSendCoinsReturn( - const WalletModel::SendCoinsReturn &sendCoinsReturn, - const QString &msgArg = QString()); - - CAmount getAmount(int unit = -1); - void removeUnmatchedOutput(CCoinControl &coinControl); - - // fee configuration - void minimizeFeeSection(bool fMinimize); - void updateFeeMinimizedLabel(); - -private: - Ui::LelantusDialog *ui; - ClientModel *clientModel; - WalletModel *walletModel; - const PlatformStyle *platformStyle; - - CAmount cachedPrivateBalance; - CAmount cachedUnconfirmedPrivateBalance; - CAmount cachedAnonymizableBalance; - - bool fFeeMinimized; - - int currentUnit; - - // coin control - CoinControlStorage coinControlStorage; -}; - -#endif // FIRO_QT_LELANTUSDIALOG_H \ No newline at end of file diff --git a/src/qt/lelantusmodel.cpp b/src/qt/lelantusmodel.cpp deleted file mode 100644 index f6795e3ebd..0000000000 --- a/src/qt/lelantusmodel.cpp +++ /dev/null @@ -1,129 +0,0 @@ -#include "../lelantus.h" -#include "../validation.h" - -#include "automintmodel.h" -#include "guiconstants.h" -#include "guiutil.h" -#include "lelantusmodel.h" - -#include -#include - -LelantusModel::LelantusModel( - const PlatformStyle *platformStyle, - CWallet *wallet, - OptionsModel *optionsModel, - QObject *parent) - : QObject(parent), - autoMintModel(0), - wallet(wallet) -{ - autoMintModel = new AutoMintModel(this, optionsModel, wallet, this); - - connect(this, &LelantusModel::ackMintAll, autoMintModel, &AutoMintModel::ackMintAll); -} - -LelantusModel::~LelantusModel() -{ - disconnect(this, &LelantusModel::ackMintAll, autoMintModel, &AutoMintModel::ackMintAll); - - delete autoMintModel; - - autoMintModel = nullptr; -} - -CAmount LelantusModel::getMintableAmount() -{ - std::vector>> valueAndUTXO; - { - LOCK2(cs_main, wallet->cs_wallet); - pwalletMain->AvailableCoinsForLMint(valueAndUTXO, nullptr); - } - - CAmount s = 0; - for (auto const &val : valueAndUTXO) { - s += val.first; - } - - return s; -} - -AutoMintModel* LelantusModel::getAutoMintModel() -{ - return autoMintModel; -} - -std::pair LelantusModel::getPrivateBalance() -{ - size_t confirmed, unconfirmed; - return pwalletMain->GetPrivateBalance(confirmed, unconfirmed); -} - -std::pair LelantusModel::getPrivateBalance(size_t &confirmed, size_t &unconfirmed) -{ - return pwalletMain->GetPrivateBalance(confirmed, unconfirmed); -} - -bool LelantusModel::unlockWallet(SecureString const &passphase, size_t msecs) -{ - LOCK2(wallet->cs_wallet, cs); - if (!wallet->Unlock(passphase)) { - return false; - } - - QTimer::singleShot(msecs, this, &LelantusModel::lock); - return true; -} - -void LelantusModel::lockWallet() -{ - LOCK2(wallet->cs_wallet, cs); - wallet->Lock(); -} - -CAmount LelantusModel::mintAll() -{ - LOCK(wallet->cs_wallet); - - std::vector> wtxAndFee; - std::vector hdMints; - - auto str = wallet->MintAndStoreLelantus(0, wtxAndFee, hdMints, true); - if (str != "") { - throw std::runtime_error("Fail to mint all public balance, " + str); - } - - CAmount s = 0; - for (auto const &wtx : wtxAndFee) { - for (auto const &out : wtx.first.tx->vout) { - if (out.scriptPubKey.IsLelantusMint()) { - s += out.nValue; - } - } - } - - return s; -} - -void LelantusModel::mintAll(AutoMintMode mode) -{ - Q_EMIT askMintAll(mode); -} - -void LelantusModel::sendAckMintAll(AutoMintAck ack, CAmount minted, QString error) -{ - Q_EMIT ackMintAll(ack, minted, error); -} - -void LelantusModel::lock() -{ - LOCK2(wallet->cs_wallet, cs); - if (autoMintModel->isAnonymizing()) { - QTimer::singleShot(MODEL_UPDATE_DELAY, this, &LelantusModel::lock); - return; - } - - if (wallet->IsCrypted() && !wallet->IsLocked()) { - lockWallet(); - } -} diff --git a/src/qt/lelantusmodel.h b/src/qt/lelantusmodel.h deleted file mode 100644 index c445e7fcbc..0000000000 --- a/src/qt/lelantusmodel.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef FIRO_QT_LELANTUSMODEL_H -#define FIRO_QT_LELANTUSMODEL_H - -#include "automintdialog.h" -#include "automintmodel.h" -#include "platformstyle.h" -#include "optionsmodel.h" -#include "walletmodel.h" - -#include -#include - -class LelantusModel : public QObject -{ - Q_OBJECT; - -public: - explicit LelantusModel( - const PlatformStyle *platformStyle, - CWallet *wallet, - OptionsModel *optionsModel, - QObject *parent = 0); - - ~LelantusModel(); - -public: - CAmount getMintableAmount(); - AutoMintModel* getAutoMintModel(); - - std::pair getPrivateBalance(); - std::pair getPrivateBalance(size_t &confirmed, size_t &unconfirmed); - - bool unlockWallet(SecureString const &passphase, size_t msecs); - void lockWallet(); - - CAmount mintAll(); - - void sendAckMintAll(AutoMintAck ack, CAmount minted = 0, QString error = QString()); - -public: - mutable CCriticalSection cs; - -Q_SIGNALS: - void askMintAll(AutoMintMode); - void ackMintAll(AutoMintAck ack, CAmount minted, QString error); - -public Q_SLOTS: - void mintAll(AutoMintMode); - void lock(); - -private: - AutoMintModel *autoMintModel; - CWallet *wallet; -}; - -#endif // FIRO_QT_LELANTUSMODEL_H \ No newline at end of file diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 507f7f604d..310d811320 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -11,7 +11,6 @@ #include "clientmodel.h" #include "guiconstants.h" #include "guiutil.h" -#include "lelantusmodel.h" #include "sparkmodel.h" #include "optionsmodel.h" #include "platformstyle.h" @@ -211,14 +210,7 @@ void OverviewPage::on_anonymizeButton_clicked() return; } - if(lelantus::IsLelantusAllowed()) { - auto lelantusModel = walletModel->getLelantusModel(); - if (!lelantusModel) { - return; - } - - lelantusModel->mintAll(AutoMintMode::MintAll); - } else if (spark::IsSparkAllowed()) { + if (spark::IsSparkAllowed()) { auto sparkModel = walletModel->getSparkModel(); if (!sparkModel) { return; @@ -255,7 +247,7 @@ void OverviewPage::setBalance( ui->labelUnconfirmedPrivate->setText(BitcoinUnits::formatWithUnit(unit, unconfirmedPrivateBalance, false, BitcoinUnits::separatorAlways)); ui->labelAnonymizable->setText(BitcoinUnits::formatWithUnit(unit, anonymizableBalance, false, BitcoinUnits::separatorAlways)); - ui->anonymizeButton->setEnabled((lelantus::IsLelantusAllowed() || spark::IsSparkAllowed()) && anonymizableBalance > 0); + ui->anonymizeButton->setEnabled(spark::IsSparkAllowed() && anonymizableBalance > 0); // only show immature (newly mined) balance if it's non-zero, so as not to complicate things // for the non-mining users @@ -312,9 +304,7 @@ void OverviewPage::setWalletModel(WalletModel *model) ui->listTransactions->setModel(filter.get()); ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress); - auto privateBalance = walletModel->getLelantusModel()->getPrivateBalance(); - std::pair sparkBalance = walletModel->getSparkBalance(); - privateBalance = spark::IsSparkAllowed() ? sparkBalance : privateBalance; + auto privateBalance = walletModel->getSparkBalance(); // Keep up to date with wallet setBalance( @@ -380,7 +370,8 @@ void OverviewPage::countDown() void OverviewPage::onRefreshClicked() { - auto privateBalance = walletModel->getLelantusModel()->getPrivateBalance(); + size_t confirmed, unconfirmed; + auto privateBalance = walletModel->getWallet()->GetPrivateBalance(confirmed, unconfirmed); auto lGracefulPeriod = ::Params().GetConsensus().nLelantusGracefulPeriod; int heightDifference = lGracefulPeriod - chainActive.Height(); const int approxBlocksPerDay = 570; @@ -404,7 +395,8 @@ void OverviewPage::onRefreshClicked() void OverviewPage::migrateClicked() { - auto privateBalance = walletModel->getLelantusModel()->getPrivateBalance(); + size_t confirmed, unconfirmed; + auto privateBalance = walletModel->getWallet()->GetPrivateBalance(confirmed, unconfirmed); auto lGracefulPeriod = ::Params().GetConsensus().nLelantusGracefulPeriod; migrateAmount = "" + BitcoinUnits::formatHtmlWithUnit(walletModel->getOptionsModel()->getDisplayUnit(), privateBalance.first); migrateAmount.append(""); diff --git a/src/qt/pcodemodel.cpp b/src/qt/pcodemodel.cpp deleted file mode 100644 index a7a369cc8d..0000000000 --- a/src/qt/pcodemodel.cpp +++ /dev/null @@ -1,257 +0,0 @@ -// Copyright (c) 2019-2021 The Firo Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "pcodemodel.h" -#include "../bip47/paymentcode.h" - -#include "bitcoinunits.h" -#include "guiutil.h" -#include "optionsmodel.h" - -#include "clientversion.h" -#include "streams.h" -#include "bip47/account.h" - -#include - -extern CCriticalSection cs_main; - -namespace { -static void OnPcodeCreated_(PcodeModel *PcodeModel, bip47::CPaymentCodeDescription const & pcodeDescr) -{ - QMetaObject::invokeMethod(PcodeModel, "DisplayCreatedPcode", Qt::AutoConnection, - Q_ARG(bip47::CPaymentCodeDescription const &, pcodeDescr)); -} -} - -PcodeModel::PcodeModel(CWallet *wallet, WalletModel *parent) : - QAbstractTableModel(parent), - walletMain(*wallet), - walletModel(parent) -{ - /* These columns must match the indices in the ColumnIndex enumeration */ - columns << tr("#") << tr("Label") << tr("RAP address"); - - wallet->NotifyPcodeCreated.connect(boost::bind(OnPcodeCreated_, this, _1)); - items = wallet->ListPcodes(); -} - -PcodeModel::~PcodeModel() -{ - walletMain.NotifyPcodeCreated.disconnect(boost::bind(OnPcodeCreated_, this, _1)); -} - -std::vector const & PcodeModel::getItems() const -{ - return items; -} - -int PcodeModel::rowCount(const QModelIndex &) const -{ - return items.size(); -} - -int PcodeModel::columnCount(const QModelIndex &) const -{ - return columns.length(); -} - -QVariant PcodeModel::data(const QModelIndex &index, int role) const -{ - if(!index.isValid() || index.row() >= int(items.size())) - return QVariant(); - - if(role == Qt::DisplayRole || role == Qt::EditRole) - { - bip47::CPaymentCodeDescription const & desc = items[index.row()]; - switch(ColumnIndex(index.column())) - { - case ColumnIndex::Number: - return int(std::get<0>(desc)); - case ColumnIndex::Pcode: - return std::get<1>(desc).toString().c_str(); - case ColumnIndex::Label: - return std::get<2>(desc).c_str(); - } - } - else if (role == Qt::TextAlignmentRole) - { - if (ColumnIndex(index.column()) == ColumnIndex::Number) - return int((Qt::AlignCenter|Qt::AlignVCenter)); - } - return QVariant(); -} - -bool PcodeModel::setData(const QModelIndex &index, const QVariant &value, int role) -{ - if(!index.isValid()) - return false; - int const row = index.row(); - if(row >= items.size()) - return false; - if(ColumnIndex(index.column()) != ColumnIndex::Label) - return false; - - if(role == Qt::EditRole) - { - std::string const newLab = value.toString().toStdString(); - if(std::get<2>(items[row]) == newLab) - return false; - - walletMain.LabelReceivingPcode(std::get<1>(items[row]), newLab); - std::get<2>(items[row]) = newLab; - Q_EMIT dataChanged(createIndex(row, int(ColumnIndex::Label)), createIndex(row, int(ColumnIndex::Label))); - return true; - } - return false; -} - -QVariant PcodeModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if(orientation == Qt::Horizontal) - { - if(role == Qt::DisplayRole && section < columns.size()) - { - return columns[section]; - } - } - return QVariant(); -} - -QModelIndex PcodeModel::index(int row, int column, const QModelIndex &parent) const -{ - Q_UNUSED(parent); - - return createIndex(row, column); -} - -Qt::ItemFlags PcodeModel::flags(const QModelIndex & index) const -{ - if(!index.isValid()) - return 0; - Qt::ItemFlags retval = Qt::ItemIsSelectable | Qt::ItemIsEnabled; - if(index.column() == int(ColumnIndex::Label)) - { - retval |= Qt::ItemIsEditable; - } - return retval; -} - -uint256 PcodeModel::sendNotificationTx(bip47::CPaymentCode const & paymentCode) -{ - LOCK2(cs_main, walletMain.cs_wallet); - return walletMain.PrepareAndSendNotificationTx(paymentCode).GetHash(); -} - -bool PcodeModel::getNotificationTxid(bip47::CPaymentCode const & paymentCode, uint256 & txid) -{ - bool result = false; - LOCK(walletMain.cs_wallet); - walletMain.GetBip47Wallet()->enumerateSenders( - [&paymentCode, &result, &txid](bip47::CAccountSender const & sender) - { - if (sender.getTheirPcode() == paymentCode && !sender.getNotificationTxId().IsNull()) { - txid = sender.getNotificationTxId(); - result = true; - return false; - } - return true; - } - ); - return result; -} - -void PcodeModel::generateTheirNextAddress(std::string const & pcode) -{ - try { - walletMain.GenerateTheirNextAddress(pcode); - } catch (std::runtime_error const &) { - LogBip47("Cannot convert to pcode: %s", pcode.c_str()); - } -} - -void PcodeModel::reconsiderBip47Tx(uint256 const & hash) -{ - LOCK(walletMain.cs_wallet); - const CWalletTx * wtx = walletMain.GetWalletTx(hash); - if (wtx && !wtx->IsCoinBase()) - walletMain.HandleBip47Transaction(*wtx); -} - -bool PcodeModel::isBip47Transaction(uint256 const & hash) const -{ - const CWalletTx * wtx = walletMain.GetWalletTx(hash); - if (wtx && !wtx->IsCoinBase()) - { - for(unsigned int i = 0; i < wtx->tx->vout.size(); i++) - { - const CTxOut& txout = wtx->tx->vout[i]; - isminetype mine = walletMain.IsMine(txout); - if (mine) - { - CTxDestination address; - if(ExtractDestination(txout.scriptPubKey, address) && IsMine(walletMain, address)) - { - boost::optional pcode = walletMain.FindPcode(address); - if (pcode) - return true; - } - } - } - } - return false; -} - -void PcodeModel::labelPcode(std::string const & pcode_, std::string const & label, bool remove) -{ - try { - walletMain.LabelSendingPcode(pcode_, label, remove); - } catch (std::runtime_error const &) { - return; - } -} - -bool PcodeModel::hasSendingPcodes() const -{ - static bool result = false; - if(!result) { - LOCK(walletMain.cs_wallet); - walletMain.GetBip47Wallet()->enumerateSenders( - [](bip47::CAccountSender const & sender) - { - result = true; - return false; - }); - } - return result; -} - -void PcodeModel::sort(int column, Qt::SortOrder order) -{ - std::function - sortPred = [&column, &order](bip47::CPaymentCodeDescription const & lhs, bip47::CPaymentCodeDescription const & rhs) - { - bip47::CPaymentCodeDescription const & cmp1 = (order == Qt::SortOrder::DescendingOrder ? lhs : rhs); - bip47::CPaymentCodeDescription const & cmp2 = (order == Qt::SortOrder::DescendingOrder ? rhs : lhs); - - switch(ColumnIndex(column)) { - case ColumnIndex::Number: - default: - return std::get<0>(cmp1) < std::get<0>(cmp2); - case ColumnIndex::Pcode: - return std::get<1>(cmp1).toString() < std::get<1>(cmp2).toString(); - case ColumnIndex::Label: - return std::get<2>(cmp1) < std::get<2>(cmp2); - } - }; - qSort(items.begin(), items.end(), sortPred); - Q_EMIT dataChanged(index(0, 0, QModelIndex()), index(items.size() - 1, int(ColumnIndex::NumberOfColumns) - 1, QModelIndex())); -} - -void PcodeModel::DisplayCreatedPcode(bip47::CPaymentCodeDescription const & pcodeDescr) -{ - beginInsertRows(QModelIndex(), 0, 0); - items.push_back(pcodeDescr); - endInsertRows(); -} diff --git a/src/qt/pcodemodel.h b/src/qt/pcodemodel.h deleted file mode 100644 index 7d9e960503..0000000000 --- a/src/qt/pcodemodel.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2019-2021 The Firo Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef PCODEMODEL_H -#define PCODEMODEL_H - -#include "walletmodel.h" -#include "../bip47/paymentcode.h" -#include -#include -#include - - -class CWallet; - -class PcodeModel: public QAbstractTableModel -{ - Q_OBJECT - -public: - explicit PcodeModel(CWallet *wallet, WalletModel *parent); - ~PcodeModel(); - - enum struct ColumnIndex : int { - Number = 0, - Label, - Pcode, - NumberOfColumns - }; - - std::vector const & getItems() const; - - int rowCount(const QModelIndex &parent) const; - int columnCount(const QModelIndex &parent) const; - QVariant data(const QModelIndex &index, int role) const; - bool setData(const QModelIndex &index, const QVariant &value, int role); - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - QModelIndex index(int row, int column, const QModelIndex &parent) const; - Qt::ItemFlags flags(const QModelIndex &index) const; - - uint256 sendNotificationTx(bip47::CPaymentCode const & paymentCode); - bool getNotificationTxid(bip47::CPaymentCode const & paymentCode, uint256 & txid); - void reconsiderBip47Tx(uint256 const & hash); - void generateTheirNextAddress(std::string const & pcode); - - bool isBip47Transaction(uint256 const & hash) const; - void labelPcode(std::string const & pcode, std::string const & label, bool remove = false); - - bool hasSendingPcodes() const; - -public Q_SLOTS: - void sort(int column, Qt::SortOrder order); - void DisplayCreatedPcode(bip47::CPaymentCodeDescription const & pcodeDescr); - -private: - CWallet & walletMain; - WalletModel *walletModel; - QStringList columns; - std::vector items; -}; - -#endif /* PCODEMODEL_H */ diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 8e5cd44bdb..0d8526a4e3 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -10,7 +10,6 @@ #include "clientmodel.h" #include "coincontroldialog.h" #include "guiutil.h" -#include "lelantusmodel.h" #include "optionsmodel.h" #include "platformstyle.h" #include "sendcoinsentry.h" @@ -24,8 +23,6 @@ #include "ui_interface.h" #include "txmempool.h" #include "wallet/wallet.h" -#include "sendtopcodedialog.h" -#include "pcodemodel.h" #include "overviewpage.h" #include @@ -97,7 +94,7 @@ SendCoinsDialog::SendCoinsDialog(const PlatformStyle *_platformStyle, QWidget *p ui->frameFee->setAutoFillBackground(true); { - auto allowed = lelantus::IsLelantusAllowed() || spark::IsSparkAllowed(); + auto allowed = spark::IsSparkAllowed(); setAnonymizeMode(allowed); if (!allowed) { @@ -158,12 +155,10 @@ void SendCoinsDialog::setModel(WalletModel *_model) } } - auto privateBalance = _model->getLelantusModel()->getPrivateBalance(); - std::pair sparkBalance = _model->getSparkBalance(); - privateBalance = spark::IsSparkAllowed() ? sparkBalance : privateBalance; + auto privateBalance = _model->getSparkBalance(); if (model->getWallet()) { - auto allowed = lelantus::IsLelantusAllowed() || (spark::IsSparkAllowed() && model->getWallet()->sparkWallet); + auto allowed = (spark::IsSparkAllowed() && model->getWallet()->sparkWallet); setAnonymizeMode(allowed); if (!allowed) { @@ -250,21 +245,6 @@ void SendCoinsDialog::on_sendButton_clicked() if(entry->validate()) { SendCoinsRecipient recipient = entry->getValue(); - if(entry->isPayToPcode()) { - if (!model->getPcodeModel()) return; - std::unique_ptr dialog(new SendtoPcodeDialog(this, recipient.address.toStdString(), recipient.label.toStdString())); - dialog->setModel(model); - dialog->exec(); - std::pair const sendResult = dialog->getResult(); - switch (sendResult.first) { - case SendtoPcodeDialog::Result::addressSelected: - recipient.address = sendResult.second.ToString().c_str(); - break; - default: - return; - } - ctx = dialog->getUnlockContext(); - } recipients.append(recipient); } else @@ -374,7 +354,8 @@ void SendCoinsDialog::on_sendButton_clicked() CAmount mintSparkAmount = 0; CAmount txFee = 0; CAmount totalAmount = 0; - if (model->getLelantusModel()->getPrivateBalance().first > 0 && spark::IsSparkAllowed() && chainActive.Height() < ::Params().GetConsensus().nLelantusGracefulPeriod) { + size_t confirmed, unconfirmed; + if (model->getWallet()->GetPrivateBalance(confirmed, unconfirmed).first > 0 && spark::IsSparkAllowed() && chainActive.Height() < ::Params().GetConsensus().nLelantusGracefulPeriod) { MigrateLelantusToSparkDialog migrateLelantusToSpark(model); bool clickedButton = migrateLelantusToSpark.getClickedButton(); if(!clickedButton) { @@ -382,9 +363,7 @@ void SendCoinsDialog::on_sendButton_clicked() return; } } - if ((fAnonymousMode == true) && !spark::IsSparkAllowed()) { - prepareStatus = model->prepareJoinSplitTransaction(currentTransaction, &ctrl); - } else if ((fAnonymousMode == true) && spark::IsSparkAllowed()) { + if ((fAnonymousMode == true) && spark::IsSparkAllowed()) { prepareStatus = model->prepareSpendSparkTransaction(currentTransaction, &ctrl); } else if ((fAnonymousMode == false) && (recipients.size() == sparkAddressCount)) { if (spark::IsSparkAllowed()) @@ -606,9 +585,7 @@ void SendCoinsDialog::on_sendButton_clicked() // now send the prepared transaction WalletModel::SendCoinsReturn sendStatus; - if ((fAnonymousMode == true) && !spark::IsSparkAllowed()) { - sendStatus = model->sendPrivateCoins(currentTransaction); - } else if ((fAnonymousMode == true) && spark::IsSparkAllowed()) { + if ((fAnonymousMode == true) && spark::IsSparkAllowed()) { sendStatus = model->spendSparkCoins(currentTransaction); } else if ((fAnonymousMode == false) && (sparkAddressCount == recipients.size()) && spark::IsSparkAllowed()) { sendStatus = model->mintSparkCoins(transactions, wtxAndFees, reservekeys); @@ -626,11 +603,6 @@ void SendCoinsDialog::on_sendButton_clicked() for(int i = 0; i < ui->entries->count(); ++i) { SendCoinsEntry *entry = qobject_cast(ui->entries->itemAt(i)->widget()); - if(entry && entry->isPayToPcode()) - { - SendCoinsRecipient recipient = entry->getValue(); - model->getPcodeModel()->generateTheirNextAddress(recipient.address.toStdString()); - } } accept(); CoinControlDialog::coinControl->UnSelectAll(); @@ -748,7 +720,7 @@ void SendCoinsDialog::updateBlocks(int count, const QDateTime& blockDate, double return; } - auto allowed = lelantus::IsLelantusAllowed() || (spark::IsSparkAllowed() && model->getWallet() && model->getWallet()->sparkWallet); + auto allowed = (spark::IsSparkAllowed() && model->getWallet() && model->getWallet()->sparkWallet); if (allowed && !ui->switchFundButton->isEnabled()) @@ -877,9 +849,7 @@ void SendCoinsDialog::setBalance( void SendCoinsDialog::updateDisplayUnit() { - auto privateBalance = model->getLelantusModel()->getPrivateBalance(); - std::pair sparkBalance = model->getSparkBalance(); - privateBalance = spark::IsSparkAllowed() ? sparkBalance : privateBalance; + auto privateBalance = model->getSparkBalance(); setBalance(model->getBalance(), 0, 0, 0, 0, 0, privateBalance.first, 0, 0); ui->customFee->setDisplayUnit(model->getOptionsModel()->getDisplayUnit()); updateMinFeeLabel(); @@ -1039,9 +1009,7 @@ void SendCoinsDialog::setAnonymizeMode(bool enableAnonymizeMode) } if (model) { - auto privateBalance = model->getLelantusModel()->getPrivateBalance(); - std::pair sparkBalance = model->getSparkBalance(); - privateBalance = spark::IsSparkAllowed() ? sparkBalance : privateBalance; + auto privateBalance = model->getSparkBalance(); setBalance(model->getBalance(), 0, 0, 0, 0, 0, privateBalance.first, 0, 0); } } diff --git a/src/qt/sendtopcodedialog.cpp b/src/qt/sendtopcodedialog.cpp deleted file mode 100644 index 9d39171037..0000000000 --- a/src/qt/sendtopcodedialog.cpp +++ /dev/null @@ -1,329 +0,0 @@ -// Copyright (c) 2019-2021 The Firo Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -// Copyright (c) 2019-2021 The Firo Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#include "sendtopcodedialog.h" -#include "ui_sendtopcodedialog.h" - -#include "addressbookpage.h" -#include "addresstablemodel.h" -#include "bitcoinunits.h" -#include "guiutil.h" -#include "optionsmodel.h" -#include "platformstyle.h" -#include "receiverequestdialog.h" -#include "recentrequeststablemodel.h" -#include "walletmodel.h" -#include "pcodemodel.h" -#include "bip47/paymentchannel.h" -#include "lelantusmodel.h" -#include "bip47/bip47utils.h" - -#include -#include -#include -#include -#include -#include - -namespace { -void OnTransactionChanged(SendtoPcodeDialog *dialog, CWallet *wallet, uint256 const &hash, ChangeType status) -{ - Q_UNUSED(wallet); - Q_UNUSED(status); - if (status == ChangeType::CT_NEW || status == ChangeType::CT_UPDATED) { - QMetaObject::invokeMethod(dialog, "onTransactionChanged", Qt::QueuedConnection, - Q_ARG(uint256, hash)); - } -} -} - -SendtoPcodeDialog::SendtoPcodeDialog(QWidget *parent, std::string const & pcode, std::string const & label) : - QDialog(parent), - ui(new Ui::SendtoPcodeDialog), - model(0), - result(Result::cancelled), - label(label), - status{} -{ - ui->setupUi(this); - try { - paymentCode = std::make_shared(pcode); - } catch (std::runtime_error const &) { - LogBip47("Cannot parse the payment code: " + pcode); - } - setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); - status.pcodeValid = true; -} - -SendtoPcodeDialog::~SendtoPcodeDialog() -{ - delete ui; - - if (!model) return; - model->getWallet()->NotifyTransactionChanged.disconnect(boost::bind(OnTransactionChanged, this, _1, _2, _3)); -} - -void SendtoPcodeDialog::setModel(WalletModel *_model) -{ - model = _model; - result = Result::cancelled; - - if (!model || !paymentCode) - return; - - model->getWallet()->NotifyTransactionChanged.connect(boost::bind(OnTransactionChanged, this, _1, _2, _3)); - - if (model->getPcodeModel()->getNotificationTxid(*paymentCode, notificationTxHash)) { - setNotifTxId(); - setUseAddr(); - } else { - ui->notificationTxIdLabel->setText(tr("None")); - } - - ui->notificationTxIdLabel->setTextFormat(Qt::RichText); - ui->notificationTxIdLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); - ui->notificationTxIdLabel->setOpenExternalLinks(true); - - std::pair lelantusBalance = model->getLelantusModel()->getPrivateBalance(); - setLelantusBalance(lelantusBalance.first, lelantusBalance.second); - - connect(model, &WalletModel::balanceChanged, this, &SendtoPcodeDialog::onBalanceChanged); - - updateButtons(); - - if(!label.empty()) - ui->pcodeLbl->setText(QString::fromStdString(label)); - else - ui->pcodeLbl->setText(QString::fromStdString(bip47::utils::ShortenPcode(*paymentCode))); -} - -void SendtoPcodeDialog::updateButtons() -{ - if (!status.pcodeValid) { - ui->sendButton->setEnabled(false); - ui->useButton->setEnabled(false); - return; - } - - if (!status.balanceOk || status.notifTxSent || status.notifTxConfirmed) { - ui->sendButton->setEnabled(false); - } else { - ui->sendButton->setEnabled(true); - } - - if (!status.notifTxSent || !status.notifTxConfirmed) { - ui->useButton->setEnabled(false); - } else if (status.notifTxConfirmed) { - ui->useButton->setEnabled(true); - } - - QString hintText = tr("Please click Connect button to start."); - QString statusText = tr("Ready to connect"); - if(!status.balanceOk) { - hintText = tr("The balance is not enough."); - statusText = tr("Balance is not enough"); - } - if(status.notifTxSent) { - hintText = tr("Please wait until the connection transaction has confirmed. " - "It is safe to close this dialog box while waiting for the confirmation. " - "Once confirmed, you can send your FIRO to the RAP address on the Send tab."); - statusText = tr("Waiting for confirmation"); - } - if(status.notifTxConfirmed) { - hintText = tr("FIRO can be sent now."); - statusText = tr("Ready"); - } - ui->hintLabel->setText(hintText); - ui->statusLabel->setText(statusText); -} - -std::pair SendtoPcodeDialog::getResult() const -{ - if (result == Result::addressSelected) { - return std::pair(result, addressToUse); - } - return std::pair(Result::cancelled, CBitcoinAddress()); -} - -std::unique_ptr SendtoPcodeDialog::getUnlockContext() -{ - return std::move(unlockContext); -} - -void SendtoPcodeDialog::close() -{ - if (!label.empty() && paymentCode) - model->getPcodeModel()->labelPcode(paymentCode->toString(), label); - QDialog::close(); -} - -int SendtoPcodeDialog::exec() -{ - if (!status.notifTxConfirmed) - return QDialog::exec(); - result = Result::addressSelected; - close(); - return 0; -} - - -void SendtoPcodeDialog::on_sendButton_clicked() -{ - if (!model || !paymentCode || !model->getPcodeModel()) - return; - - unlockContext = std::unique_ptr(new WalletModel::UnlockContext(model->requestUnlock())); - if (!unlockContext->isValid()) - return; - - try { - notificationTxHash = model->getPcodeModel()->sendNotificationTx(*paymentCode); - setNotifTxId(); - setUseAddr(); - status.notifTxSent = true; - updateButtons(); - } - catch (std::runtime_error const & e) - { - QMessageBox msgBox; - msgBox.setText(tr( - "During creation of the notification tx the following error occurred:\n")); - msgBox.setInformativeText(e.what()); - msgBox.setWindowTitle(tr("RAP error")); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.exec(); - } -} - -void SendtoPcodeDialog::on_useButton_clicked() -{ - result = Result::addressSelected; - close(); -} - -void SendtoPcodeDialog::on_cancelButton_clicked() -{ - result = Result::cancelled; - close(); -} - -void SendtoPcodeDialog::on_helpButton_clicked() -{ - QMessageBox msgBox; - msgBox.setText(tr( - "Sending funds to a RAP address requires a notification transaction to be sent by the payer prior to the first payment. \n" - "Notification transactions use Lelantus facilities to enhance privacy.\n" - "After the notification transaction is received by the RAP address issuer, funds can be privately sent to the RAP secret addresses.\n")); - msgBox.setInformativeText(tr( - "The recommended workflow is as follows:\n" - "1. Send a notification transaction\n" - "2. Make sure it is included in a block with a block explorer\n" - "3. Send funds to the RAP address in one or more transactions")); - msgBox.setWindowTitle(tr("RAP info")); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.exec(); -} - -void SendtoPcodeDialog::showEvent( QShowEvent* event ) { - QDialog::showEvent( event); - adjustSize(); - ui->balanceSpacer->sizeHint().setHeight(ui->sendButton->size().height()); - - QTimer::singleShot(10, this, &SendtoPcodeDialog::onWindowShown); -} - -void SendtoPcodeDialog::setNotifTxId() -{ - std::ostringstream ostr; - ostr << "" << notificationTxHash.GetHex() << ""; - ui->notificationTxIdLabel->setText(ostr.str().c_str()); - - status.notifTxSent = true; - - CWalletTx const * notifTx = model->getWallet()->GetWalletTx(notificationTxHash); - if (!notifTx) return; - int notifTxDepth = 0; - { - LOCK(cs_main); - notifTxDepth = notifTx->GetDepthInMainChain(); - } - - if (notifTxDepth > 0) - { - status.notifTxConfirmed = true; - updateButtons(); - } -} - -void SendtoPcodeDialog::setUseAddr() -{ - { - LOCK(model->getWallet()->cs_wallet); - addressToUse = model->getWallet()->GetTheirNextAddress(*paymentCode); - } -} - -void SendtoPcodeDialog::setLelantusBalance(CAmount const & lelantusBalance, CAmount const & unconfirmedLelantusBalance) -{ - if (!model) return; - int const unit = model->getOptionsModel()->getDisplayUnit(); - QString balancePretty = BitcoinUnits::formatWithUnit(unit, lelantusBalance, false, BitcoinUnits::separatorAlways); - if (lelantusBalance < bip47::NotificationTxValue) - balancePretty += " (pending: " + BitcoinUnits::formatWithUnit(unit, unconfirmedLelantusBalance, false, BitcoinUnits::separatorAlways) + ")"; - - ui->balanceLabel->setText(balancePretty); - - QColor color(GUIUtil::GUIColors::checkPassed); - if (lelantusBalance < bip47::NotificationTxValue) { - color = QColor(GUIUtil::GUIColors::warning); - status.balanceOk = false; - } else { - status.balanceOk = true; - } - ui->balanceLabel->setStyleSheet("QLabel { color: " + color.name() + "; }"); - updateButtons(); -} - -void SendtoPcodeDialog::onTransactionChanged(uint256 txHash) -{ - if (txHash != notificationTxHash) return; - setNotifTxId(); -} - -void SendtoPcodeDialog::onWindowShown() -{ - if(!model->getPcodeModel()->hasSendingPcodes()) { - QMessageBox msgBox; - msgBox.setText(tr( - "A one time connection fee is required when sending to a new RAP address.\n" - "Once this fee is paid, all future sends to this RAP address do not incur any additional fee.\n" - )); - msgBox.setWindowTitle(tr("RAP info")); - msgBox.setStandardButtons(QMessageBox::Ok); - msgBox.setDefaultButton(QMessageBox::Ok); - msgBox.exec(); - } -} - -void SendtoPcodeDialog::onBalanceChanged( - const CAmount& balance, - const CAmount& unconfirmedBalance, - const CAmount& immatureBalance, - const CAmount& watchOnlyBalance, - const CAmount& watchUnconfBalance, - const CAmount& watchImmatureBalance, - const CAmount& privateBalance, - const CAmount& unconfirmedPrivateBalance, - const CAmount& anonymizableBalance) -{ - setLelantusBalance(privateBalance, unconfirmedPrivateBalance); -} diff --git a/src/qt/sendtopcodedialog.h b/src/qt/sendtopcodedialog.h deleted file mode 100644 index 7c1b899239..0000000000 --- a/src/qt/sendtopcodedialog.h +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) 2019-2021 The Firo Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef BITCOIN_QT_SENDTOPCODEDIALOG_H -#define BITCOIN_QT_SENDTOPCODEDIALOG_H - -#include "guiutil.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "walletmodel.h" -#include "bip47/paymentcode.h" - -class OptionsModel; -class PlatformStyle; -class WalletModel; - -namespace Ui { - class SendtoPcodeDialog; -} - -QT_BEGIN_NAMESPACE -class QModelIndex; -QT_END_NAMESPACE - -/** Dialog for requesting payment of bitcoins */ -class SendtoPcodeDialog : public QDialog -{ - Q_OBJECT - -public: - enum struct Result : int { - cancelled = 0, - addressSelected, - }; - - explicit SendtoPcodeDialog(QWidget *parent, std::string const & pcode, std::string const & label); - ~SendtoPcodeDialog(); - - void setModel(WalletModel *model); - std::pair getResult() const; - std::unique_ptr getUnlockContext(); - - void setUseAddr(); - void close(); - int exec() override; - -private: - Ui::SendtoPcodeDialog *ui; - WalletModel *model; - std::shared_ptr paymentCode; - Result result; - std::string label; - uint256 notificationTxHash; - CBitcoinAddress addressToUse; - std::unique_ptr unlockContext; - struct Status - { - bool pcodeValid; - bool balanceOk; - bool notifTxSent; - bool notifTxConfirmed; - }; - Status status; - - void setNotifTxId(); - void setLelantusBalance(CAmount const & amount, CAmount const & unconfirmedLelantusBalance); - void updateButtons(); - -private Q_SLOTS: - void on_sendButton_clicked(); - void on_useButton_clicked(); - void on_cancelButton_clicked(); - void on_helpButton_clicked(); - void showEvent(QShowEvent* event); - void onTransactionChanged(uint256 txHash); - void onWindowShown(); - void onBalanceChanged(CAmount const &, CAmount const &, CAmount const &, CAmount const &, CAmount const &, CAmount const &, CAmount const &, CAmount const &, CAmount const &); -}; - -#endif /* SENDTOPCODEDIALOG_H */ - diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index 7ad14a9ac5..10e4d810a3 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -16,7 +16,6 @@ #include "transactionrecord.h" #include "transactiontablemodel.h" #include "walletmodel.h" -#include "pcodemodel.h" #include "ui_interface.h" @@ -162,7 +161,6 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa // Actions abandonAction = new QAction(tr("Abandon transaction"), this); resendAction = new QAction(tr("Re-broadcast transaction"), this); - reconsiderBip47TxAction = new QAction(tr("Reconsider BIP47 transaction"), this); QAction *copyAddressAction = new QAction(tr("Copy address"), this); copyLabelAction = new QAction(tr(CopyLabelText), this); @@ -185,8 +183,6 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa contextMenu->addAction(abandonAction); contextMenu->addAction(editLabelAction); contextMenu->addAction(resendAction); - contextMenu->addAction(reconsiderBip47TxAction); - // Connect actions @@ -212,7 +208,6 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa connect(showDetailsAction, &QAction::triggered, this, &TransactionView::showDetails); connect(this, &TransactionView::doubleClicked, this, &TransactionView::showDetails); connect(resendAction, &QAction::triggered, this, &TransactionView::rebroadcastTx); - connect(reconsiderBip47TxAction, &QAction::triggered, this, &TransactionView::reconsiderBip47Tx); } void TransactionView::setModel(WalletModel *_model) @@ -418,7 +413,6 @@ void TransactionView::contextualMenu(const QPoint &point) copyLabelAction->setText(tr(CopyLabelText)); abandonAction->setEnabled(model->transactionCanBeAbandoned(hash)); resendAction->setEnabled(model->transactionCanBeRebroadcast(hash)); - reconsiderBip47TxAction->setVisible(model->getWallet()->IsCrypted() && model->getPcodeModel()->isBip47Transaction(hash)); if(index.isValid()) { @@ -487,20 +481,6 @@ void TransactionView::rebroadcastTx() model->getTransactionTableModel()->updateTransaction(hashQStr, CT_UPDATED, true); } -void TransactionView::reconsiderBip47Tx() -{ - if(!transactionView || !transactionView->selectionModel()) - return; - QModelIndexList selection = transactionView->selectionModel()->selectedRows(0); - - // get the hash from the TxHashRole (QVariant / QString) - uint256 hash; - QString hashQStr = selection.at(0).data(TransactionTableModel::TxHashRole).toString(); - hash.SetHex(hashQStr.toStdString()); - - model->getPcodeModel()->reconsiderBip47Tx(hash); -} - void TransactionView::copyAddress() { GUIUtil::copyEntryData(transactionView, 0, TransactionTableModel::AddressRole); diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h index 5b78cce3f7..540e6252af 100644 --- a/src/qt/transactionview.h +++ b/src/qt/transactionview.h @@ -86,7 +86,6 @@ class TransactionView : public QWidget QAction *copyLabelAction; QAction *abandonAction; QAction *resendAction; - QAction *reconsiderBip47TxAction; QWidget *createDateRangeWidget(); void updateCalendarWidgets(); @@ -109,7 +108,6 @@ private Q_SLOTS: void updateWatchOnlyColumn(bool fHaveWatchOnly); void abandonTx(); void rebroadcastTx(); - void reconsiderBip47Tx(); Q_SIGNALS: void doubleClicked(const QModelIndex&); diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp index 06ca9a2868..982049f5c3 100644 --- a/src/qt/walletframe.cpp +++ b/src/qt/walletframe.cpp @@ -160,13 +160,6 @@ void WalletFrame::gotoSignMessageTab(QString addr) walletView->gotoSignMessageTab(addr); } -void WalletFrame::gotoLelantusPage() -{ - QMap::const_iterator i; - for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i) - i.value()->gotoLelantusPage(); -} - void WalletFrame::gotoVerifyMessageTab(QString addr) { WalletView *walletView = currentWalletView(); diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h index 2c99bd74bd..594522f42f 100644 --- a/src/qt/walletframe.h +++ b/src/qt/walletframe.h @@ -78,8 +78,6 @@ public Q_SLOTS: void gotoReceiveCoinsPage(); /** Switch to send coins page */ void gotoSendCoinsPage(QString addr = ""); - /** Switch to lelantus page */ - void gotoLelantusPage(); /** Show Sign/Verify Message dialog and switch to sign message tab */ void gotoSignMessageTab(QString addr = ""); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 66a8538941..97b4cfc2a0 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -8,12 +8,10 @@ #include "consensus/validation.h" #include "guiconstants.h" #include "guiutil.h" -#include "lelantusmodel.h" #include "sparkmodel.h" #include "paymentserver.h" #include "recentrequeststablemodel.h" #include "transactiontablemodel.h" -#include "pcodemodel.h" #include "base58.h" #include "keystore.h" @@ -44,11 +42,9 @@ WalletModel::WalletModel(const PlatformStyle *platformStyle, CWallet *_wallet, OptionsModel *_optionsModel, QObject *parent) : QObject(parent), wallet(_wallet), optionsModel(_optionsModel), addressTableModel(0), pcodeAddressTableModel(0), - lelantusModel(0), sparkModel(0), transactionTableModel(0), recentRequestsTableModel(0), - pcodeModel(0), cachedBalance(0), cachedUnconfirmedBalance(0), cachedImmatureBalance(0), cachedEncryptionStatus(Unencrypted), cachedNumBlocks(0), @@ -59,11 +55,9 @@ WalletModel::WalletModel(const PlatformStyle *platformStyle, CWallet *_wallet, O addressTableModel = new AddressTableModel(wallet, this); pcodeAddressTableModel = new PcodeAddressTableModel(wallet, this); - lelantusModel = new LelantusModel(platformStyle, wallet, _optionsModel, this); sparkModel = new SparkModel(platformStyle, wallet, _optionsModel, this); transactionTableModel = new TransactionTableModel(platformStyle, wallet, this); recentRequestsTableModel = new RecentRequestsTableModel(wallet, this); - pcodeModel = new PcodeModel(wallet, this); // This timer will be fired repeatedly to update the balance pollTimer = new QTimer(this); @@ -98,9 +92,7 @@ CAmount WalletModel::getBalance(const CCoinControl *coinControl, bool fExcludeLo CAmount WalletModel::getAnonymizableBalance() const { CAmount amount = 0; - if(lelantus::IsLelantusAllowed()) { - amount = lelantusModel->getMintableAmount(); - } else if (spark::IsSparkAllowed()){ + if (spark::IsSparkAllowed()){ amount = sparkModel->getMintableSparkAmount(); } return amount; @@ -182,11 +174,7 @@ void WalletModel::checkBalanceChanged() CAmount newPrivateBalance, newUnconfirmedPrivateBalance; std::tie(newPrivateBalance, newUnconfirmedPrivateBalance) = - lelantusModel->getPrivateBalance(); - - std::pair sparkBalance = getSparkBalance(); - newPrivateBalance = spark::IsSparkAllowed() ? sparkBalance.first : newPrivateBalance; - newUnconfirmedPrivateBalance = spark::IsSparkAllowed() ? sparkBalance.second : newUnconfirmedPrivateBalance; + getSparkBalance(); if (haveWatchOnly()) { @@ -367,201 +355,6 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact return SendCoinsReturn(OK); } -WalletModel::SendCoinsReturn WalletModel::prepareJoinSplitTransaction( - WalletModelTransaction &transaction, - const CCoinControl *coinControl) -{ - CAmount total = 0; - bool fSubtractFeeFromAmount = false; - QList recipients = transaction.getRecipients(); - std::vector vecSend; - - if(recipients.empty()) - { - return OK; - } - - QSet setAddress; // Used to detect duplicates - int nAddresses = 0; - - // Pre-check input data for validity - for (const SendCoinsRecipient &rcp : recipients) - { - if (rcp.fSubtractFeeFromAmount) - fSubtractFeeFromAmount = true; - - { - // User-entered Firo address / amount: - if(!validateAddress(rcp.address)) - { - return InvalidAddress; - } - if(rcp.amount <= 0) - { - return InvalidAmount; - } - setAddress.insert(rcp.address); - ++nAddresses; - - CScript scriptPubKey = GetScriptForDestination(CBitcoinAddress(rcp.address.toStdString()).Get()); - CRecipient recipient = {scriptPubKey, rcp.amount, rcp.fSubtractFeeFromAmount}; - vecSend.push_back(recipient); - - total += rcp.amount; - } - } - if(setAddress.size() != nAddresses) - { - return DuplicateAddress; - } - - CAmount nBalance; - std::tie(nBalance, std::ignore) = lelantusModel->getPrivateBalance(); - - if(total > nBalance) - { - return AmountExceedsBalance; - } - - { - LOCK2(cs_main, wallet->cs_wallet); - - auto &spendCoins = transaction.getSpendCoins(); - auto &sigmaSpendCoins = transaction.getSigmaSpendCoins(); - auto &mintCoins = transaction.getMintCoins(); - - CAmount feeRequired = 0; - std::string strFailReason; - - CWalletTx *newTx = transaction.getTransaction(); - try { - *newTx = wallet->CreateLelantusJoinSplitTransaction(vecSend, feeRequired, {}, spendCoins, sigmaSpendCoins, mintCoins, coinControl); - } catch (InsufficientFunds const&) { - transaction.setTransactionFee(feeRequired); - if (!fSubtractFeeFromAmount && (total + feeRequired) > nBalance) { - return SendCoinsReturn(AmountWithFeeExceedsBalance); - } - return SendCoinsReturn(AmountExceedsBalance); - } catch (std::runtime_error const &e) { - Q_EMIT message( - tr("Send Coins"), - QString::fromStdString(e.what()), - CClientUIInterface::MSG_ERROR); - - return TransactionCreationFailed; - } catch (std::invalid_argument const &e) { - Q_EMIT message( - tr("Send Coins"), - QString::fromStdString(e.what()), - CClientUIInterface::MSG_ERROR); - - return TransactionCreationFailed; - } - - // reject absurdly high fee. (This can never happen because the - // wallet caps the fee at maxTxFee. This merely serves as a - // belt-and-suspenders check) - if (feeRequired > maxTxFee) { - return AbsurdFee; - } - - int changePos = -1; - if (!mintCoins.empty()) { - for (changePos = 0; changePos < newTx->tx->vout.size(); changePos++) { - if (newTx->tx->vout[changePos].scriptPubKey.IsLelantusJMint()) { - break; - } - } - - changePos = changePos >= newTx->tx->vout.size() ? -1 : changePos; - } - - transaction.setTransactionFee(feeRequired); - transaction.reassignAmounts(changePos); - } - - return SendCoinsReturn(OK); -} - -WalletModel::SendCoinsReturn WalletModel::prepareMintTransactions( - CAmount amount, - std::vector &transactions, - std::list &reserveKeys, - std::vector &mints, - const CCoinControl *coinControl) -{ - if (amount <= 0) { - return InvalidAmount; - } - - auto balance = getBalance(coinControl); - if (amount > balance) { - return AmountExceedsBalance; - } - - std::vector> wtxAndFees; - CAmount allFee = 0; - int changePos = -1; - std::string failReason; - - bool success = false; - try { - success = wallet->CreateLelantusMintTransactions( - amount, wtxAndFees, allFee, mints, reserveKeys, changePos, failReason, coinControl); - - } catch (std::runtime_error const &e) { - return SendCoinsReturn(TransactionCreationFailed, e.what()); - } - - - transactions.clear(); - transactions.reserve(wtxAndFees.size()); - for (auto &wtxAndFee : wtxAndFees) { - auto &wtx = wtxAndFee.first; - auto fee = wtxAndFee.second; - - QList recipients; - - int changePos = -1; - for (size_t i = 0; i != wtx.tx->vout.size(); i++) { - if (wtx.tx->vout[i].scriptPubKey.IsMint()) { - SendCoinsRecipient r; - r.amount = wtx.tx->vout[i].nValue; - recipients.push_back(r); - } else { - changePos = i; - } - } - - transactions.emplace_back(recipients); - auto &tx = transactions.back(); - - *tx.getTransaction() = wtx; - tx.setTransactionFee(fee); - - tx.reassignAmounts(changePos); - } - - if (!success) { - if (amount + allFee > balance) { - return SendCoinsReturn(AmountWithFeeExceedsBalance); - } - - Q_EMIT message( - tr("Coin Anonymizing"), - QString::fromStdString(failReason), - CClientUIInterface::MSG_ERROR); - - return TransactionCommitFailed; - } - - if (allFee > maxTxFee) { - return WalletModel::AbsurdFee; - } - - return SendCoinsReturn(OK); -} - WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &transaction) { QByteArray transaction_array; /* store serialized transaction */ @@ -617,90 +410,6 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran return SendCoinsReturn(OK); } -WalletModel::SendCoinsReturn WalletModel::sendPrivateCoins(WalletModelTransaction &transaction) -{ - QByteArray transaction_array; /* store serialized transaction */ - - { - LOCK2(cs_main, wallet->cs_wallet); - CWalletTx *newTx = transaction.getTransaction(); - - for (const SendCoinsRecipient &rcp : transaction.getRecipients()) - { - if (!rcp.message.isEmpty()) // Message from normal firo:URI (firo:123...?message=example) - newTx->vOrderForm.push_back(make_pair("Message", rcp.message.toStdString())); - } - - try { - if (!wallet->CommitLelantusTransaction(*newTx, transaction.getSpendCoins(), transaction.getSigmaSpendCoins(), transaction.getMintCoins())) - return SendCoinsReturn(TransactionCommitFailed); - } catch (std::runtime_error const &e) { - return SendCoinsReturn(TransactionCommitFailed, e.what()); - } - - CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); - ssTx << *newTx->tx; - transaction_array.append(&(ssTx[0]), ssTx.size()); - } - - // Add addresses / update labels that we've sent to to the address book, - // and emit coinsSent signal for each recipient - for (const SendCoinsRecipient &rcp : transaction.getRecipients()) - { - { - std::string strAddress = rcp.address.toStdString(); - CTxDestination dest = CBitcoinAddress(strAddress).Get(); - std::string strLabel = rcp.label.toStdString(); - { - LOCK(wallet->cs_wallet); - - std::map::iterator mi = wallet->mapAddressBook.find(dest); - - // Check if we have a new address or an updated label - if (mi == wallet->mapAddressBook.end()) - { - wallet->SetAddressBook(dest, strLabel, "send"); - } - else if (mi->second.name != strLabel) - { - wallet->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose - } - } - } - Q_EMIT coinsSent(wallet, rcp, transaction_array); - } - checkBalanceChanged(); // update balance immediately, otherwise there could be a short noticeable delay until pollBalanceChanged hits - - return SendCoinsReturn(OK); -} - -WalletModel::SendCoinsReturn WalletModel::sendAnonymizingCoins( - std::vector &transactions, - std::list &reservekeys, - std::vector &mints) -{ - auto reservekey = reservekeys.begin(); - CWalletDB db(wallet->strWalletFile); - - for (size_t i = 0; i != transactions.size(); i++) { - - auto tx = transactions[i].getTransaction(); - - CValidationState state; - if (!wallet->CommitTransaction(*tx, *reservekey++, g_connman.get(), state)) { - return TransactionCommitFailed; - } - - auto &mintTmp = mints[i]; - mintTmp.SetTxHash(tx->GetHash()); - { - wallet->zwallet->GetTracker().AddLelantus(db, mintTmp, true); - } - } - wallet->zwallet->UpdateCountDB(db); - return SendCoinsReturn(OK); -} - OptionsModel *WalletModel::getOptionsModel() { return optionsModel; @@ -716,11 +425,6 @@ PcodeAddressTableModel *WalletModel::getPcodeAddressTableModel() return pcodeAddressTableModel; } -LelantusModel *WalletModel::getLelantusModel() -{ - return lelantusModel; -} - SparkModel *WalletModel::getSparkModel() { return sparkModel; @@ -736,11 +440,6 @@ RecentRequestsTableModel *WalletModel::getRecentRequestsTableModel() return recentRequestsTableModel; } -PcodeModel *WalletModel::getPcodeModel() -{ - return pcodeModel; -} - WalletModel::EncryptionStatus WalletModel::getEncryptionStatus() const { if(!wallet->IsCrypted()) @@ -1339,7 +1038,7 @@ bool WalletModel::getAvailableLelantusCoins() } else { return false; } -} +} bool WalletModel::migrateLelantusToSpark() { diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index f7e85ef62c..69529eb202 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -21,14 +21,12 @@ class AddressTableModel; class PcodeAddressTableModel; -class LelantusModel; class SparkModel; class OptionsModel; class PlatformStyle; class RecentRequestsTableModel; class TransactionTableModel; class WalletModelTransaction; -class PcodeModel; class CCoinControl; class CKeyID; @@ -132,11 +130,9 @@ class WalletModel : public QObject OptionsModel *getOptionsModel(); AddressTableModel *getAddressTableModel(); PcodeAddressTableModel *getPcodeAddressTableModel(); - LelantusModel *getLelantusModel(); SparkModel *getSparkModel(); TransactionTableModel *getTransactionTableModel(); RecentRequestsTableModel *getRecentRequestsTableModel(); - PcodeModel *getPcodeModel(); CWallet *getWallet() const { return wallet; } @@ -172,17 +168,6 @@ class WalletModel : public QObject // prepare transaction for getting txfee before sending coins SendCoinsReturn prepareTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl = NULL); - // prepare transaction for getting txfee before sending coins in anonymous mode - SendCoinsReturn prepareJoinSplitTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl = NULL); - - // prepare transaction for getting txfee before anonymizing coins - SendCoinsReturn prepareMintTransactions( - CAmount amount, - std::vector &transactions, - std::list &reserveKeys, - std::vector &mints, - const CCoinControl *coinControl); - SendCoinsReturn prepareMintSparkTransaction( std::vector &transactions, QList recipients, @@ -204,21 +189,11 @@ class WalletModel : public QObject ); bool migrateLelantusToSpark(); - + bool getAvailableLelantusCoins(); // Send coins to a list of recipients SendCoinsReturn sendCoins(WalletModelTransaction &transaction); - - // Send private coins to a list of recipients - SendCoinsReturn sendPrivateCoins(WalletModelTransaction &transaction); - - // Anonymize coins. - SendCoinsReturn sendAnonymizingCoins( - std::vector &transactions, - std::list &reservekeys, - std::vector &mints); - // Wallet encryption bool setWalletEncrypted(bool encrypted, const SecureString &passphrase); // Passphrase only needed when unlocking @@ -300,11 +275,9 @@ class WalletModel : public QObject AddressTableModel *addressTableModel; PcodeAddressTableModel *pcodeAddressTableModel; - LelantusModel *lelantusModel; SparkModel *sparkModel; TransactionTableModel *transactionTableModel; RecentRequestsTableModel *recentRequestsTableModel; - PcodeModel *pcodeModel; // Cache some values to be able to detect changes CAmount cachedBalance; diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp index eb65f9fa6b..e41f0000af 100644 --- a/src/qt/walletview.cpp +++ b/src/qt/walletview.cpp @@ -11,8 +11,6 @@ #include "bitcoingui.h" #include "clientmodel.h" #include "guiutil.h" -#include "lelantusdialog.h" -#include "lelantusmodel.h" #include "sparkmodel.h" #include "optionsmodel.h" #include "overviewpage.h" @@ -43,8 +41,6 @@ WalletView::WalletView(const PlatformStyle *_platformStyle, QWidget *parent): clientModel(0), walletModel(0), overviewPage(0), - lelantusView(0), - // blankLelantusView(0), firoTransactionsView(0), platformStyle(_platformStyle) { @@ -53,26 +49,20 @@ WalletView::WalletView(const PlatformStyle *_platformStyle, QWidget *parent): receiveCoinsPage = new ReceiveCoinsDialog(platformStyle); usedSendingAddressesPage = new AddressBookPage(platformStyle, AddressBookPage::ForEditing, AddressBookPage::SendingTab, this); usedReceivingAddressesPage = new AddressBookPage(platformStyle, AddressBookPage::ForEditing, AddressBookPage::ReceivingTab, this, false); - lelantusPage = new QWidget(this); sendCoinsPage = new QWidget(this); masternodeListPage = new MasternodeList(platformStyle); - automintNotification = new AutomintNotification(this); - automintNotification->setWindowModality(Qt::NonModal); - automintSparkNotification = new AutomintSparkNotification(this); automintSparkNotification->setWindowModality(Qt::NonModal); setupTransactionPage(); setupSendCoinPage(); - setupLelantusPage(); addWidget(overviewPage); addWidget(transactionsPage); addWidget(receiveCoinsPage); addWidget(sendCoinsPage); - addWidget(lelantusPage); addWidget(masternodeListPage); // Clicking on a transaction on the overview pre-selects the transaction on the transaction history page @@ -136,23 +126,6 @@ void WalletView::setupSendCoinPage() sendCoinsPage->setLayout(pageLayout); } -void WalletView::setupLelantusPage() -{ - auto pageLayout = new QVBoxLayout(); - - // if (pwalletMain->IsHDSeedAvailable()) { - lelantusView = new LelantusDialog(platformStyle); - connect(lelantusView, &LelantusDialog::message, this, &WalletView::message); - pageLayout->addWidget(lelantusView); - // } else { - - // blankLelantusView = new BlankSigmaDialog(); - // pageLayout->addWidget(blankLelantusView); - // } - - lelantusPage->setLayout(pageLayout); -} - void WalletView::setBitcoinGUI(BitcoinGUI *gui) { if (gui) @@ -183,10 +156,6 @@ void WalletView::setClientModel(ClientModel *_clientModel) overviewPage->setClientModel(clientModel); sendFiroView->setClientModel(clientModel); masternodeListPage->setClientModel(clientModel); - - if (pwalletMain->IsHDSeedAvailable()) { - lelantusView->setClientModel(clientModel); - } } void WalletView::setWalletModel(WalletModel *_walletModel) @@ -199,14 +168,10 @@ void WalletView::setWalletModel(WalletModel *_walletModel) receiveCoinsPage->setModel(_walletModel); // TODO: fix this //sendCoinsPage->setModel(_walletModel); - if (pwalletMain->IsHDSeedAvailable()) { - lelantusView->setWalletModel(_walletModel); - } usedReceivingAddressesPage->setModel(_walletModel->getAddressTableModel()); usedSendingAddressesPage->setModel(_walletModel->getAddressTableModel()); masternodeListPage->setWalletModel(_walletModel); sendFiroView->setModel(_walletModel); - automintNotification->setModel(_walletModel); automintSparkNotification->setModel(_walletModel); if (_walletModel) @@ -231,16 +196,7 @@ void WalletView::setWalletModel(WalletModel *_walletModel) connect(_walletModel, &WalletModel::showProgress, this, &WalletView::showProgress); // Check mintable amount - connect(_walletModel, &WalletModel::balanceChanged, this, &WalletView::checkMintableAmount); - - auto lelantusModel = _walletModel->getLelantusModel(); - if (lelantusModel) { - connect(lelantusModel, &LelantusModel::askMintAll, this, &WalletView::askMintAll); - auto autoMintModel = lelantusModel->getAutoMintModel(); - connect(autoMintModel, &AutoMintModel::message, this, &WalletView::message); - connect(autoMintModel, &AutoMintModel::requireShowAutomintNotification, this, &WalletView::showAutomintNotification); - connect(autoMintModel, &AutoMintModel::closeAutomintNotification, this, &WalletView::closeAutomintNotification); - } + connect(_walletModel, &WalletModel::balanceChanged, this, &WalletView::checkMintableSparkAmount); auto sparkModel = _walletModel->getSparkModel(); if (sparkModel) { @@ -304,11 +260,6 @@ void WalletView::gotoReceiveCoinsPage() setCurrentWidget(receiveCoinsPage); } -void WalletView::gotoLelantusPage() -{ - setCurrentWidget(lelantusPage); -} - void WalletView::gotoSendCoinsPage(QString addr) { setCurrentWidget(sendCoinsPage); @@ -461,51 +412,6 @@ void WalletView::requestedSyncWarningInfo() Q_EMIT outOfSyncWarningClicked(); } -void WalletView::showAutomintNotification() -{ - auto lelantusModel = walletModel->getLelantusModel(); - if (!lelantusModel) { - return; - } - - if (!isActiveWindow() || !underMouse()) { - lelantusModel->sendAckMintAll(AutoMintAck::WaitUserToActive); - return; - } - - automintNotification->setWindowFlags(automintNotification->windowFlags() | Qt::Popup | Qt::FramelessWindowHint); - - QRect rect(this->mapToGlobal(QPoint(0, 0)), this->size()); - auto pos = QStyle::alignedRect( - Qt::LeftToRight, - Qt::AlignRight | Qt::AlignBottom, - automintNotification->size(), - rect).topLeft(); - - pos.setX(pos.x()); - pos.setY(pos.y()); - automintNotification->move(pos); - - automintNotification->show(); - automintNotification->raise(); -} - -void WalletView::repositionAutomintNotification() -{ - if (automintNotification->isVisible()) { - QRect rect(this->mapToGlobal(QPoint(0, 0)), this->size()); - auto pos = QStyle::alignedRect( - Qt::LeftToRight, - Qt::AlignRight | Qt::AlignBottom, - automintNotification->size(), - rect).topLeft(); - - pos.setX(pos.x()); - pos.setY(pos.y()); - automintNotification->move(pos); - } -} - void WalletView::showAutomintSparkNotification() { auto sparkModel = walletModel->getSparkModel(); @@ -551,14 +457,6 @@ void WalletView::repositionAutomintSparkNotification() } } -void WalletView::checkMintableAmount(CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount anonymizableBalance) -{ - if (automintNotification->isVisible() && anonymizableBalance == 0) { - // hide if notification is showing but there no any fund to anonymize - closeAutomintNotification(); - } -} - void WalletView::checkMintableSparkAmount(CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount anonymizableBalance) { if (automintSparkNotification->isVisible() && anonymizableBalance == 0) { @@ -567,29 +465,11 @@ void WalletView::checkMintableSparkAmount(CAmount, CAmount, CAmount, CAmount, CA } } -void WalletView::closeAutomintNotification() -{ - automintNotification->close(); -} - void WalletView::closeAutomintSparkNotification() { automintSparkNotification->close(); } -void WalletView::askMintAll(AutoMintMode mode) -{ - automintNotification->setVisible(false); - - if (!walletModel) { - return; - } - - AutoMintDialog dlg(mode, this); - dlg.setModel(walletModel); - dlg.exec(); -} - void WalletView::askMintSparkAll(AutoMintSparkMode mode) { automintSparkNotification->setVisible(false); @@ -608,7 +488,7 @@ bool WalletView::eventFilter(QObject *watched, QEvent *event) switch (event->type()) { case QEvent::Type::Resize: case QEvent::Type::Move: - repositionAutomintNotification(); + repositionAutomintSparkNotification(); break; } diff --git a/src/qt/walletview.h b/src/qt/walletview.h index b0203dd00c..91934b93af 100644 --- a/src/qt/walletview.h +++ b/src/qt/walletview.h @@ -13,7 +13,6 @@ #include "automintnotification.h" #include "amount.h" #include "masternodelist.h" -#include "lelantusdialog.h" #include @@ -68,7 +67,6 @@ class WalletView : public QStackedWidget private: void setupTransactionPage(); void setupSendCoinPage(); - void setupLelantusPage(); private: ClientModel *clientModel; @@ -82,8 +80,6 @@ class WalletView : public QStackedWidget AddressBookPage *usedReceivingAddressesPage; QWidget *sendCoinsPage; SendCoinsDialog *sendFiroView; - LelantusDialog *lelantusView; - QWidget *lelantusPage; TransactionView *firoTransactionList; QWidget *firoTransactionsView; MasternodeList *masternodeListPage; @@ -91,7 +87,6 @@ class WalletView : public QStackedWidget QProgressDialog *progressDialog; const PlatformStyle *platformStyle; - AutomintNotification *automintNotification; AutomintSparkNotification *automintSparkNotification; public Q_SLOTS: @@ -109,8 +104,6 @@ public Q_SLOTS: void gotoReceiveCoinsPage(); /** Switch to send coins page */ void gotoSendCoinsPage(QString addr = ""); - /** Switch to lelantus page */ - void gotoLelantusPage(); /** Show Sign/Verify Message dialog and switch to sign message tab */ void gotoSignMessageTab(QString addr = ""); @@ -149,30 +142,19 @@ public Q_SLOTS: void requestedSyncWarningInfo(); /** Show automint notification */ - void showAutomintNotification(); - void showAutomintSparkNotification(); /** Re-position automint notification */ - void repositionAutomintNotification(); - void repositionAutomintSparkNotification(); /** Check mintable amount to close automint notification */ - void checkMintableAmount( - CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount anonymizableBalance); - void checkMintableSparkAmount( CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount, CAmount anonymizableBalance); /** Close automint notification */ - void closeAutomintNotification(); - void closeAutomintSparkNotification(); /** Ask user to do auto mint */ - void askMintAll(AutoMintMode mode); - void askMintSparkAll(AutoMintSparkMode mode); Q_SIGNALS: From 8bcf65ffcb1142c1bfcf13eaff4da4dc46a2a227 Mon Sep 17 00:00:00 2001 From: levonpetrosyan93 Date: Mon, 12 Aug 2024 13:40:39 +0400 Subject: [PATCH 2/7] More improvements --- src/qt/transactionrecord.cpp | 12 ++++-------- src/qt/transactiontablemodel.cpp | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 5360253cdc..1daa7ec600 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -47,17 +47,13 @@ QList TransactionRecord::decomposeTransaction(const CWallet * std::map mapValue = wtx.mapValue; bool isAllSigmaSpendFromMe = false; - for (const auto& vin : wtx.tx->vin) { - isAllSigmaSpendFromMe = (wallet->IsMine(vin, *wtx.tx) & ISMINE_SPENDABLE) && vin.IsSigmaSpend(); - if (!isAllSigmaSpendFromMe) - break; + if (wtx.tx->vin[0].IsSigmaSpend()) { + isAllSigmaSpendFromMe = (wallet->IsMine(wtx.tx->vin[0], *wtx.tx) & ISMINE_SPENDABLE); } bool isAllJoinSplitFromMe = false; - for (const auto& vin : wtx.tx->vin) { - isAllJoinSplitFromMe = (wallet->IsMine(vin, *wtx.tx) & ISMINE_SPENDABLE) && vin.IsLelantusJoinSplit(); - if (!isAllJoinSplitFromMe) - break; + if (wtx.tx->vin[0].IsLelantusJoinSplit()) { + isAllJoinSplitFromMe = (wallet->IsMine(wtx.tx->vin[0], *wtx.tx) & ISMINE_SPENDABLE); } if (wtx.tx->IsZerocoinSpend() || isAllSigmaSpendFromMe || isAllJoinSplitFromMe) { diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index d65f7577f7..40a32b1283 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -279,7 +279,7 @@ void TransactionTableModel::updateConfirmations() // Invalidate status (number of confirmations) and (possibly) description // for all rows. Qt is smart enough to only actually request the data for the // visible rows. - int numRows = std::min(1000, priv->size()-1); + int numRows = std::min(300, priv->size()-1); Q_EMIT dataChanged(index(0, Status), index(numRows, Status)); Q_EMIT dataChanged(index(0, ToAddress), index(numRows, ToAddress)); } From 96930a608b609ff8a3d0bfc2782a887d3b65a029 Mon Sep 17 00:00:00 2001 From: firstcryptoman Date: Wed, 11 Sep 2024 03:18:25 +0400 Subject: [PATCH 3/7] Fixed UI hang issue during batch verification --- src/qt/clientmodel.cpp | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 023c012a36..e299c404a3 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -70,7 +70,7 @@ int ClientModel::getNumConnections(unsigned int flags) const void ClientModel::setMasternodeList(const CDeterministicMNList& mnList) { - LOCK(cs_mnlinst); + TRY_LOCK(cs_mnlinst,lock); if (mnListCached.GetBlockHash() == mnList.GetBlockHash()) { return; } @@ -80,19 +80,25 @@ void ClientModel::setMasternodeList(const CDeterministicMNList& mnList) CDeterministicMNList ClientModel::getMasternodeList() const { - LOCK(cs_mnlinst); + TRY_LOCK(cs_mnlinst,lock); return mnListCached; } void ClientModel::refreshMasternodeList() { - LOCK(cs_mnlinst); + TRY_LOCK(cs_mnlinst,lock); + if(!lock){ + return; + } setMasternodeList(deterministicMNManager->GetListAtChainTip()); } int ClientModel::getNumBlocks() const { - LOCK(cs_main); + TRY_LOCK(cs_main,lock); + if (!lock) { + return -1; + } return chainActive.Height(); } @@ -101,7 +107,10 @@ int ClientModel::getHeaderTipHeight() const if (cachedBestHeaderHeight == -1) { // make sure we initially populate the cache via a cs_main lock // otherwise we need to wait for a tip update - LOCK(cs_main); + TRY_LOCK(cs_main,lock); + if (!lock) { + return cachedBestHeaderHeight; + } if (pindexBestHeader) { cachedBestHeaderHeight = pindexBestHeader->nHeight; cachedBestHeaderTime = pindexBestHeader->GetBlockTime(); @@ -113,7 +122,10 @@ int ClientModel::getHeaderTipHeight() const int64_t ClientModel::getHeaderTipTime() const { if (cachedBestHeaderTime == -1) { - LOCK(cs_main); + TRY_LOCK(cs_main,lock); + if (!lock) { + return cachedBestHeaderTime; + } if (pindexBestHeader) { cachedBestHeaderHeight = pindexBestHeader->nHeight; cachedBestHeaderTime = pindexBestHeader->GetBlockTime(); @@ -138,7 +150,7 @@ quint64 ClientModel::getTotalBytesSent() const QDateTime ClientModel::getLastBlockDate() const { - LOCK(cs_main); + TRY_LOCK(cs_main,lock); if (chainActive.Tip()) return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime()); @@ -161,7 +173,7 @@ double ClientModel::getVerificationProgress(const CBlockIndex *tipIn) const CBlockIndex *tip = const_cast(tipIn); if (!tip) { - LOCK(cs_main); + TRY_LOCK(cs_main,lock); tip = chainActive.Tip(); } return GuessVerificationProgress(Params().TxData(), tip); From 631e7a3f76f4a8f309dd4266c9de231eac168073 Mon Sep 17 00:00:00 2001 From: levonpetrosyan93 Date: Thu, 17 Oct 2024 06:27:56 +0400 Subject: [PATCH 4/7] QT hanging improvements --- src/qt/automintmodel.cpp | 57 ++++++++++++++++++++++------ src/qt/clientmodel.cpp | 6 +++ src/qt/sparkmodel.cpp | 7 +++- src/qt/transactiontablemodel.cpp | 32 +++++++++++++--- src/qt/walletmodel.cpp | 65 +++++++++++++++++++++++++++----- 5 files changed, 140 insertions(+), 27 deletions(-) diff --git a/src/qt/automintmodel.cpp b/src/qt/automintmodel.cpp index a78c55dc26..bb891e1dc3 100644 --- a/src/qt/automintmodel.cpp +++ b/src/qt/automintmodel.cpp @@ -34,7 +34,9 @@ IncomingFundNotifier::~IncomingFundNotifier() void IncomingFundNotifier::newBlock() { - LOCK(cs); + TRY_LOCK(cs, lock); + if(!lock) + return; if (!txs.empty()) { resetTimer(); @@ -43,7 +45,9 @@ void IncomingFundNotifier::newBlock() void IncomingFundNotifier::pushTransaction(uint256 const &id) { - LOCK(cs); + TRY_LOCK(cs, lock); + if(!lock) + return; txs.push_back(id); resetTimer(); @@ -51,7 +55,9 @@ void IncomingFundNotifier::pushTransaction(uint256 const &id) void IncomingFundNotifier::check() { - LOCK(cs); + TRY_LOCK(cs, lock); + if(!lock) + return; // update only if there are transaction and last update was done more than 2 minutes ago, and in case it is first time if (txs.empty() || (lastUpdateTime!= 0 && (GetSystemTimeInSeconds() - lastUpdateTime <= 120))) { @@ -64,7 +70,12 @@ void IncomingFundNotifier::check() std::vector immatures; { - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return; CCoinControl coinControl; coinControl.nCoinType = CoinType::ONLY_NOT1000IFMN; while (!txs.empty()) { @@ -104,8 +115,16 @@ void IncomingFundNotifier::check() void IncomingFundNotifier::importTransactions() { - LOCK(cs); - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs, lock); + if(!lock) + return; + + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return; for (auto const &tx : wallet->mapWallet) { if (tx.second.GetAvailableCredit() > 0 || tx.second.GetImmatureCredit() > 0) { @@ -207,7 +226,9 @@ void AutoMintSparkModel::ackMintSparkAll(AutoMintSparkAck ack, CAmount minted, Q { bool mint = false; { - LOCK(sparkModel->cs); + TRY_LOCK(sparkModel->cs, lock); + if(!lock) + return; if (autoMintSparkState == AutoMintSparkState::Disabled) { // Do nothing return; @@ -244,7 +265,9 @@ void AutoMintSparkModel::checkAutoMintSpark(bool force) } { - LOCK(sparkModel->cs); + TRY_LOCK(sparkModel->cs, lock); + if(!lock) + return; if (fReindex) { return; @@ -284,7 +307,12 @@ void AutoMintSparkModel::startAutoMintSpark() CAmount mintable = 0; { - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return; mintable = sparkModel->getMintableSparkAmount(); } @@ -299,8 +327,15 @@ void AutoMintSparkModel::startAutoMintSpark() void AutoMintSparkModel::updateAutoMintSparkOption(bool enabled) { - LOCK2(cs_main, wallet->cs_wallet); - LOCK(sparkModel->cs); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return; + TRY_LOCK(sparkModel->cs, lock); + if (!lock) + return; if (enabled) { if (autoMintSparkState == AutoMintSparkState::Disabled) { diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index e299c404a3..c85925bf40 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -71,6 +71,9 @@ int ClientModel::getNumConnections(unsigned int flags) const void ClientModel::setMasternodeList(const CDeterministicMNList& mnList) { TRY_LOCK(cs_mnlinst,lock); + if (!lock) + return; + if (mnListCached.GetBlockHash() == mnList.GetBlockHash()) { return; } @@ -81,6 +84,9 @@ void ClientModel::setMasternodeList(const CDeterministicMNList& mnList) CDeterministicMNList ClientModel::getMasternodeList() const { TRY_LOCK(cs_mnlinst,lock); + if (!lock) + return CDeterministicMNList(); + return mnListCached; } diff --git a/src/qt/sparkmodel.cpp b/src/qt/sparkmodel.cpp index 3d2682c156..05c970cc63 100644 --- a/src/qt/sparkmodel.cpp +++ b/src/qt/sparkmodel.cpp @@ -37,7 +37,12 @@ CAmount SparkModel::getMintableSparkAmount() { std::vector>> valueAndUTXO; { - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return 0; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return 0; pwalletMain->AvailableCoinsForLMint(valueAndUTXO, nullptr); } diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index 9fcf80088a..d769933200 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -82,7 +82,12 @@ class TransactionTablePriv qDebug() << "TransactionTablePriv::refreshWallet"; cachedWallet.clear(); { - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return; for(std::map::iterator it = wallet->mapWallet.begin(); it != wallet->mapWallet.end(); ++it) { if(TransactionRecord::showTransaction(it->second)) @@ -131,7 +136,12 @@ class TransactionTablePriv } if(showTransaction) { - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return; // Find transaction in wallet std::map::iterator mi = wallet->mapWallet.find(hash); if(mi == wallet->mapWallet.end()) @@ -213,9 +223,14 @@ class TransactionTablePriv QString describe(TransactionRecord *rec, int unit) { { - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return QString();; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return QString(); std::map::iterator mi = wallet->mapWallet.find(rec->hash); - if(mi != wallet->mapWallet.end()) + if (mi != wallet->mapWallet.end()) { return TransactionDesc::toHTML(wallet, mi->second, rec, unit); } @@ -225,9 +240,14 @@ class TransactionTablePriv QString getTxHex(TransactionRecord *rec) { - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return QString(); + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return QString(); std::map::iterator mi = wallet->mapWallet.find(rec->hash); - if(mi != wallet->mapWallet.end()) + if (mi != wallet->mapWallet.end()) { std::string strHex = EncodeHexTx(static_cast(mi->second)); return QString::fromStdString(strHex); diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 97b4cfc2a0..60af984d50 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -728,7 +728,13 @@ bool WalletModel::getPrivKey(const CKeyID &address, CKey& vchPrivKeyOut) const // returns a list of COutputs from COutPoints void WalletModel::getOutputs(const std::vector& vOutpoints, std::vector& vOutputs, boost::optional fMintTabSelected) { - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return; + BOOST_FOREACH(const COutPoint& outpoint, vOutpoints) { if (!wallet->mapWallet.count(outpoint.hash)) continue; @@ -751,7 +757,12 @@ void WalletModel::getOutputs(const std::vector& vOutpoints, std::vect bool WalletModel::isSpent(const COutPoint& outpoint) const { - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return false; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return false; return wallet->IsSpent(outpoint.hash, outpoint.n); } @@ -763,7 +774,13 @@ void WalletModel::listCoins(std::map >& mapCoins, coinControl.nCoinType = nCoinType; wallet->AvailableCoins(vCoins, true, &coinControl, false); - LOCK2(cs_main, wallet->cs_wallet); // ListLockedCoins, mapWallet + TRY_LOCK(cs_main,lock_main); // ListLockedCoins, mapWallet + if (!lock_main) + return; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return; + std::vector vLockedCoins; wallet->ListLockedCoins(vLockedCoins); @@ -816,39 +833,69 @@ void WalletModel::listCoins(std::map >& mapCoins, bool WalletModel::isLockedCoin(uint256 hash, unsigned int n) const { - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return false; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return false; return wallet->IsLockedCoin(hash, n); } void WalletModel::lockCoin(COutPoint& output) { - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return; wallet->LockCoin(output); Q_EMIT updateMintable(); } void WalletModel::unlockCoin(COutPoint& output) { - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return; wallet->UnlockCoin(output); Q_EMIT updateMintable(); } void WalletModel::listLockedCoins(std::vector& vOutpts) { - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return; wallet->ListLockedCoins(vOutpts); } void WalletModel::listProTxCoins(std::vector& vOutpts) { - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return; wallet->ListProTxCoins(vOutpts); } bool WalletModel::hasMasternode() { - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return false; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return false; return wallet->HasMasternode(); } From 7ec3281416e1501dc276f73ce67c4c09dafbfd2d Mon Sep 17 00:00:00 2001 From: levonpetrosyan93 Date: Fri, 18 Oct 2024 04:11:26 +0400 Subject: [PATCH 5/7] QT hanging fix --- src/qt/masternodelist.cpp | 4 +++- src/qt/transactiondesc.cpp | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/qt/masternodelist.cpp b/src/qt/masternodelist.cpp index 685a845434..3911ee295e 100644 --- a/src/qt/masternodelist.cpp +++ b/src/qt/masternodelist.cpp @@ -165,7 +165,9 @@ void MasternodeList::updateDIP3List() { // Get all UTXOs for each MN collateral in one go so that we can reduce locking overhead for cs_main // We also do this outside of the below Qt list update loop to reduce cs_main locking time to a minimum - LOCK(cs_main); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return; mnList.ForEachMN(false, [&](const CDeterministicMNCPtr& dmn) { CTxDestination collateralDest; Coin coin; diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index a13eb7e347..1a15a1ab52 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -72,7 +72,12 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco { QString strHTML; - LOCK2(cs_main, wallet->cs_wallet); + TRY_LOCK(cs_main,lock_main); + if (!lock_main) + return strHTML; + TRY_LOCK(wallet->cs_wallet,lock_wallet); + if (!lock_wallet) + return strHTML; strHTML.reserve(4000); strHTML += ""; From 3ae2e270e9378631efd8a4be060de44197da46f9 Mon Sep 17 00:00:00 2001 From: levonpetrosyan93 Date: Sun, 3 Nov 2024 07:10:00 +0400 Subject: [PATCH 6/7] Review commits applied --- src/qt/clientmodel.cpp | 19 ++++++++++++++----- src/qt/clientmodel.h | 4 ++++ src/qt/sparkmodel.cpp | 5 +++-- src/qt/sparkmodel.h | 2 ++ src/qt/transactiontablemodel.cpp | 25 ++++++++++++++++++++----- src/qt/transactiontablemodel.h | 2 +- 6 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index c85925bf40..2c9458b295 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -38,6 +38,8 @@ ClientModel::ClientModel(OptionsModel *_optionsModel, QObject *parent) : { cachedBestHeaderHeight = -1; cachedBestHeaderTime = -1; + cachedNumBlocks = 0; + cachedLastBlockDate = QDateTime(); peerTableModel = new PeerTableModel(this); banTableModel = new BanTableModel(this); pollTimer = new QTimer(this); @@ -102,10 +104,10 @@ void ClientModel::refreshMasternodeList() int ClientModel::getNumBlocks() const { TRY_LOCK(cs_main,lock); - if (!lock) { - return -1; + if (lock) { + cachedNumBlocks = chainActive.Height(); } - return chainActive.Height(); + return cachedNumBlocks; } int ClientModel::getHeaderTipHeight() const @@ -158,8 +160,13 @@ QDateTime ClientModel::getLastBlockDate() const { TRY_LOCK(cs_main,lock); - if (chainActive.Tip()) - return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime()); + if (!lock) + cachedLastBlockDate; + + if (chainActive.Tip()) { + cachedLastBlockDate = QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime()); + return cachedLastBlockDate; + } return QDateTime::fromTime_t(Params().GenesisBlock().GetBlockTime()); // Genesis block's time of current network } @@ -180,6 +187,8 @@ double ClientModel::getVerificationProgress(const CBlockIndex *tipIn) const if (!tip) { TRY_LOCK(cs_main,lock); + if (!lock) + return 0; tip = chainActive.Tip(); } return GuessVerificationProgress(Params().TxData(), tip); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 750633c15a..90312f0f7b 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -93,6 +93,10 @@ class ClientModel : public QObject mutable std::atomic cachedBestHeaderHeight; mutable std::atomic cachedBestHeaderTime; + mutable std::atomic cachedNumBlocks; + mutable QDateTime cachedLastBlockDate; + + private: OptionsModel *optionsModel; PeerTableModel *peerTableModel; diff --git a/src/qt/sparkmodel.cpp b/src/qt/sparkmodel.cpp index 05c970cc63..6b7c36cb97 100644 --- a/src/qt/sparkmodel.cpp +++ b/src/qt/sparkmodel.cpp @@ -39,10 +39,10 @@ CAmount SparkModel::getMintableSparkAmount() { TRY_LOCK(cs_main,lock_main); if (!lock_main) - return 0; + return cachedMintableSparkAmount; TRY_LOCK(wallet->cs_wallet,lock_wallet); if (!lock_wallet) - return 0; + return cachedMintableSparkAmount; pwalletMain->AvailableCoinsForLMint(valueAndUTXO, nullptr); } @@ -51,6 +51,7 @@ CAmount SparkModel::getMintableSparkAmount() s += val.first; } + cachedMintableSparkAmount = s; return s; } diff --git a/src/qt/sparkmodel.h b/src/qt/sparkmodel.h index 6564cf0521..04d2e6d585 100644 --- a/src/qt/sparkmodel.h +++ b/src/qt/sparkmodel.h @@ -40,6 +40,8 @@ class SparkModel : public QObject public: mutable CCriticalSection cs; + mutable std::atomic cachedMintableSparkAmount; + Q_SIGNALS: void askMintSparkAll(AutoMintSparkMode); void ackMintSparkAll(AutoMintSparkAck ack, CAmount minted, QString error); diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index d769933200..d15ae81e62 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -16,7 +16,6 @@ #include "core_io.h" #include "validation.h" #include "sync.h" -#include "uint256.h" #include "util.h" #include "wallet/wallet.h" @@ -74,6 +73,7 @@ class TransactionTablePriv * this is sorted by sha256. */ QList cachedWallet; + std::vector>> cachedUpdatedTx; /* Query entire wallet anew from core. */ @@ -137,11 +137,15 @@ class TransactionTablePriv if(showTransaction) { TRY_LOCK(cs_main,lock_main); - if (!lock_main) + if (!lock_main) { + cachedUpdatedTx.push_back(std::make_pair(hash, std::make_pair(status, showTransaction))); return; + } TRY_LOCK(wallet->cs_wallet,lock_wallet); - if (!lock_wallet) + if (!lock_wallet) { + cachedUpdatedTx.push_back(std::make_pair(hash, std::make_pair(status, showTransaction))); return; + } // Find transaction in wallet std::map::iterator mi = wallet->mapWallet.find(hash); if(mi == wallet->mapWallet.end()) @@ -289,8 +293,19 @@ void TransactionTableModel::updateTransaction(const QString &hash, int status, b { uint256 updated; updated.SetHex(hash.toStdString()); - - priv->updateWallet(updated, status, showTransaction); + priv->cachedUpdatedTx.push_back(std::make_pair(updated, std::make_pair(status, showTransaction))); + size_t currentSize = priv->cachedUpdatedTx.size(); + for (auto itr = priv->cachedUpdatedTx.rbegin(); itr!= priv->cachedUpdatedTx.rend();) + { + std::pair> current = *itr; + priv->cachedUpdatedTx.erase(--priv->cachedUpdatedTx.end()); + itr++; + priv->updateWallet(current.first, current.second.first, current.second.second); + // this thread was not able to perform the update, stop and do it next time + if (currentSize == priv->cachedUpdatedTx.size()) + break; + currentSize = priv->cachedUpdatedTx.size(); + } } void TransactionTableModel::updateConfirmations() diff --git a/src/qt/transactiontablemodel.h b/src/qt/transactiontablemodel.h index 8ec4a61554..d25a4acde3 100644 --- a/src/qt/transactiontablemodel.h +++ b/src/qt/transactiontablemodel.h @@ -6,7 +6,7 @@ #define BITCOIN_QT_TRANSACTIONTABLEMODEL_H #include "bitcoinunits.h" - +#include "uint256.h" #include #include From 24e276116e860edb9caf231035d3c866b6851fc8 Mon Sep 17 00:00:00 2001 From: levonpetrosyan93 Date: Mon, 11 Nov 2024 08:50:12 +0400 Subject: [PATCH 7/7] coderabbit comments applied --- src/qt/clientmodel.cpp | 2 +- src/qt/transactiontablemodel.cpp | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 2c9458b295..e9643758ff 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -161,7 +161,7 @@ QDateTime ClientModel::getLastBlockDate() const TRY_LOCK(cs_main,lock); if (!lock) - cachedLastBlockDate; + return cachedLastBlockDate; if (chainActive.Tip()) { cachedLastBlockDate = QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime()); diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index d15ae81e62..f1d3157db7 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -295,11 +295,10 @@ void TransactionTableModel::updateTransaction(const QString &hash, int status, b updated.SetHex(hash.toStdString()); priv->cachedUpdatedTx.push_back(std::make_pair(updated, std::make_pair(status, showTransaction))); size_t currentSize = priv->cachedUpdatedTx.size(); - for (auto itr = priv->cachedUpdatedTx.rbegin(); itr!= priv->cachedUpdatedTx.rend();) + while (!priv->cachedUpdatedTx.empty()) { - std::pair> current = *itr; - priv->cachedUpdatedTx.erase(--priv->cachedUpdatedTx.end()); - itr++; + std::pair> current = priv->cachedUpdatedTx.back(); + priv->cachedUpdatedTx.pop_back(); priv->updateWallet(current.first, current.second.first, current.second.second); // this thread was not able to perform the update, stop and do it next time if (currentSize == priv->cachedUpdatedTx.size())