From dd1c92aeb74600f2c8b7b12ad18001c245fd3ff4 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Sat, 14 Aug 2021 16:16:45 +0200 Subject: [PATCH 01/23] Update Monero submodule --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9efc6412..ce756700 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ if(DEBUG) set(CMAKE_VERBOSE_MAKEFILE ON) endif() -set(MONERO_HEAD "d0662146e12d9c0ac9905b4423bb27bd68a4444e") +set(MONERO_HEAD "25ec90f4ddeb19c31553f0104a18d80974f9acb8") set(BUILD_GUI_DEPS ON) option(ARCH "Target architecture" "x86-64") set(BUILD_64 ON) From 98130b620822ae67c524102fab4887147ffcaada Mon Sep 17 00:00:00 2001 From: tobtoht Date: Sat, 14 Aug 2021 16:20:22 +0200 Subject: [PATCH 02/23] Add melo.tools onion nodes --- src/assets/nodes.json | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/assets/nodes.json b/src/assets/nodes.json index 181fda8a..9cc66ce2 100644 --- a/src/assets/nodes.json +++ b/src/assets/nodes.json @@ -7,7 +7,8 @@ "3hvpnd4xejtzcuowvru2wfjum5wjf7synigm44rrizr3k4v5vzam2bad.onion:18081", "rbpgdckle3h3vi4wwwrh75usqtoc5r3alohy7yyx57isynvay63nacyd.onion:18089", "6dsdenp6vjkvqzy4wzsnzn6wixkdzihx3khiumyzieauxuxslmcaeiad.onion:18081", - "56wl7y2ebhamkkiza4b7il4mrzwtyvpdym7bm2bkg3jrei2je646k3qd.onion:18089" + "56wl7y2ebhamkkiza4b7il4mrzwtyvpdym7bm2bkg3jrei2je646k3qd.onion:18089", + "melo7jwjspngus3xhbt5kxeqc4njhokyvh55jfmehplglgmb7a6rb6yd.onion:18081" ], "clearnet": [ "node.melo.tools:18081", @@ -25,14 +26,17 @@ ] }, "testnet": { - "tor": [], + "tor": [ + "melot6vncfusj5gfi73gaosea2mc572n3n7f7gof75zkwg6oibkhk3id.onion:28081" + ], "clearnet": [ "testnet.melo.tools:28081" ] }, "stagenet": { "tor": [ - "ct36dsbe3oubpbebpxmiqz4uqk6zb6nhmkhoekileo4fts23rvuse2qd.onion:38081" + "ct36dsbe3oubpbebpxmiqz4uqk6zb6nhmkhoekileo4fts23rvuse2qd.onion:38081", + "melos2hbwolcavwbgytdwbmcx7t3uh2eu36p3vnbttibosnpzmtp6hqd.onion:38081" ], "clearnet": [ "super.fast.node.xmr.pm:38089", From 05512945e982207dcf3fbfe3eedec26cb20b4074 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Sat, 14 Aug 2021 16:22:21 +0200 Subject: [PATCH 03/23] Rename core logfile --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 46fef960..68501959 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -139,7 +139,7 @@ if (AttachConsole(ATTACH_PARENT_PROCESS)) { } // Setup logging - QString logPath = QString("%1/daemon.log").arg(configDir); + QString logPath = QString("%1/libwallet.log").arg(configDir); Monero::Utils::onStartup(); Monero::Wallet::init("", "feather", logPath.toStdString(), true); From 3eca0bad874d9a98b3869349b36c4cb6dc21af53 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Sat, 14 Aug 2021 16:39:51 +0200 Subject: [PATCH 04/23] History: Don't use info icon on resend transaction --- src/HistoryWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HistoryWidget.cpp b/src/HistoryWidget.cpp index e31390de..bf835d13 100644 --- a/src/HistoryWidget.cpp +++ b/src/HistoryWidget.cpp @@ -84,7 +84,7 @@ void HistoryWidget::showContextMenu(const QPoint &point) { bool unconfirmed = tx->isFailed() || tx->isPending(); if (unconfirmed && tx->direction() != TransactionInfo::Direction_In) { - menu.addAction(icons()->icon("info2.svg"), "Resend transaction", this, &HistoryWidget::onResendTransaction); + menu.addAction("Resend transaction", this, &HistoryWidget::onResendTransaction); } menu.addMenu(m_copyMenu); From 1e6832c1846ec03f9cde0593d1c731228994b8bb Mon Sep 17 00:00:00 2001 From: tobtoht Date: Sat, 14 Aug 2021 16:53:22 +0200 Subject: [PATCH 05/23] Don't allow manually storing wallet during synchronization --- src/MainWindow.cpp | 12 +++++++++++- src/MainWindow.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index c6121649..914e0447 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -236,7 +236,7 @@ void MainWindow::initMenu() { connect(ui->actionViewOnly, &QAction::triggered, this, &MainWindow::showViewOnlyDialog); // [Wallet] -> [Advanced] - connect(ui->actionStore_wallet, &QAction::triggered, [this]{m_ctx->wallet->store();}); + connect(ui->actionStore_wallet, &QAction::triggered, this, &MainWindow::tryStoreWallet); connect(ui->actionUpdate_balance, &QAction::triggered, [this]{m_ctx->updateBalance();}); connect(ui->actionRefresh_tabs, &QAction::triggered, [this]{m_ctx->refreshModels();}); connect(ui->actionRescan_spent, &QAction::triggered, this, &MainWindow::rescanSpent); @@ -530,6 +530,16 @@ void MainWindow::setStatusText(const QString &text, bool override, int timeout) } } +void MainWindow::tryStoreWallet() { + if (m_ctx->wallet->connectionStatus() == Wallet::ConnectionStatus::ConnectionStatus_Synchronizing) { + QMessageBox::warning(this, "Save wallet", "Unable to save wallet during synchronization.\n\n" + "Wait until synchronization is finished and try again."); + return; + } + + m_ctx->wallet->store(); +} + void MainWindow::onSynchronized() { this->updateNetStats(); this->setStatusText("Synchronized"); diff --git a/src/MainWindow.h b/src/MainWindow.h index 6def9ddd..883329d0 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -180,6 +180,7 @@ private slots: void onUpdatesAvailable(const QJsonObject &updates); void toggleSearchbar(bool enabled); void onSetStatusText(const QString &text); + void tryStoreWallet(); private: friend WindowManager; From b76636daa6a1e3a34f51ba9e714faf1898aaeaea Mon Sep 17 00:00:00 2001 From: tobtoht Date: Sat, 14 Aug 2021 16:57:39 +0200 Subject: [PATCH 06/23] Use node instead of daemon in user-facing strings --- src/MainWindow.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 914e0447..a7584394 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -600,11 +600,11 @@ void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QVecto qCritical() << tx_err; if (m_ctx->wallet->connectionStatus() == Wallet::ConnectionStatus_WrongVersion) - err = QString("%1 Wrong daemon version: %2").arg(err).arg(tx_err); + err = QString("%1 Wrong node version: %2").arg(err).arg(tx_err); else err = QString("%1 %2").arg(err).arg(tx_err); - if (tx_err.contains("Daemon response did not include the requested real output")) { + if (tx_err.contains("Node response did not include the requested real output")) { QString currentNode = m_ctx->nodes->connection().toAddress(); err += QString("\nYou are currently connected to: %1\n\n" @@ -726,7 +726,7 @@ void MainWindow::showConnectionStatusDialog() { QString statusMsg; switch(status){ case Wallet::ConnectionStatus_Disconnected: - statusMsg = "Wallet is disconnected from daemon."; + statusMsg = "Wallet is disconnected from node."; break; case Wallet::ConnectionStatus_Connecting: { auto node = m_ctx->nodes->connection(); @@ -734,7 +734,7 @@ void MainWindow::showConnectionStatusDialog() { break; } case Wallet::ConnectionStatus_WrongVersion: - statusMsg = "Wallet is connected to incompatible daemon."; + statusMsg = "Wallet is connected to incompatible node."; break; case Wallet::ConnectionStatus_Synchronizing: case Wallet::ConnectionStatus_Synchronized: { From c9775affd22b809e0e455b597813df6dead39157 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Sat, 14 Aug 2021 17:02:03 +0200 Subject: [PATCH 07/23] View-only: add toolip for disabled button --- src/dialog/ViewOnlyDialog.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/dialog/ViewOnlyDialog.cpp b/src/dialog/ViewOnlyDialog.cpp index 160c0f79..a031a1a2 100644 --- a/src/dialog/ViewOnlyDialog.cpp +++ b/src/dialog/ViewOnlyDialog.cpp @@ -22,7 +22,11 @@ ViewOnlyDialog::ViewOnlyDialog(QSharedPointer ctx, QWidget *parent) connect(ui->btn_Copy, &QPushButton::clicked, this, &ViewOnlyDialog::copyToClipboad); connect(ui->btn_Save, &QPushButton::clicked, this, &ViewOnlyDialog::onWriteViewOnlyWallet); - ui->btn_Save->setEnabled(!m_ctx->wallet->viewOnly()); + if (m_ctx->wallet->viewOnly()) { + ui->btn_Save->setEnabled(false); + ui->btn_Save->setToolTip("Wallet is already view-only"); + } + this->adjustSize(); } From 3288b85071224dc5938ccce27477603bfadb20d2 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Sat, 14 Aug 2021 17:14:27 +0200 Subject: [PATCH 08/23] Nodes: don't append http:// on add custom node --- src/widgets/NodeWidget.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/widgets/NodeWidget.cpp b/src/widgets/NodeWidget.cpp index 23d6afa0..3b94d892 100644 --- a/src/widgets/NodeWidget.cpp +++ b/src/widgets/NodeWidget.cpp @@ -135,8 +135,9 @@ void NodeWidget::onCustomAddClicked(){ auto currentNodes = m_ctx->nodes->customNodes(); QString currentNodesText; - for (auto &entry: currentNodes) - currentNodesText += QString("%1\n").arg(entry.url.toString()); + for (auto &entry: currentNodes) { + currentNodesText += QString("%1\n").arg(entry.toFullAddress()); + } bool ok; QString text = QInputDialog::getMultiLineText(this, "Add custom node(s).", "E.g: user:password@127.0.0.1:18081", currentNodesText, &ok); @@ -145,9 +146,9 @@ void NodeWidget::onCustomAddClicked(){ QList nodesList; auto newNodesList = text.split("\n"); - for(auto &newNodeText: newNodesList) { + for (auto &newNodeText: newNodesList) { newNodeText = newNodeText.replace("\r", "").trimmed(); - if(newNodeText.isEmpty()) + if (newNodeText.isEmpty()) continue; auto node = FeatherNode(newNodeText); From f09e973e56a2fd404218b62df5dcf0717a6b59db Mon Sep 17 00:00:00 2001 From: tobtoht Date: Sat, 14 Aug 2021 17:39:15 +0200 Subject: [PATCH 09/23] TxConfAdvDialog: export tx key --- src/dialog/TxConfAdvDialog.cpp | 9 ++++++ src/dialog/TxConfAdvDialog.h | 3 ++ src/dialog/TxConfAdvDialog.ui | 51 ++++++++++++++++++++++++---------- 3 files changed, 48 insertions(+), 15 deletions(-) diff --git a/src/dialog/TxConfAdvDialog.cpp b/src/dialog/TxConfAdvDialog.cpp index fda8f53a..8261849f 100644 --- a/src/dialog/TxConfAdvDialog.cpp +++ b/src/dialog/TxConfAdvDialog.cpp @@ -19,6 +19,7 @@ TxConfAdvDialog::TxConfAdvDialog(QSharedPointer ctx, const QString & , m_ctx(std::move(ctx)) , m_exportUnsignedMenu(new QMenu(this)) , m_exportSignedMenu(new QMenu(this)) + , m_exportTxKeyMenu(new QMenu(this)) { ui->setupUi(this); @@ -31,6 +32,9 @@ TxConfAdvDialog::TxConfAdvDialog(QSharedPointer ctx, const QString & m_exportSignedMenu->addAction("Save to file", this, &TxConfAdvDialog::signedSaveFile); ui->btn_exportSigned->setMenu(m_exportSignedMenu); + m_exportTxKeyMenu->addAction("Copy to clipboard", this, &TxConfAdvDialog::txKeyCopy); + ui->btn_exportTxKey->setMenu(m_exportTxKeyMenu); + if (m_ctx->wallet->viewOnly()) { ui->btn_exportSigned->hide(); ui->btn_send->hide(); @@ -80,6 +84,7 @@ void TxConfAdvDialog::setUnsignedTransaction(UnsignedTransaction *utx) { ui->btn_exportUnsigned->hide(); ui->btn_exportSigned->hide(); + ui->btn_exportTxKey->hide(); ui->btn_sign->show(); ui->btn_send->hide(); @@ -166,6 +171,10 @@ void TxConfAdvDialog::signedCopy() { Utils::copyToClipboard(m_tx->signedTxToHex(0)); } +void TxConfAdvDialog::txKeyCopy() { + Utils::copyToClipboard(m_tx->transaction(0)->txKey()); +} + void TxConfAdvDialog::signedQrCode() { } diff --git a/src/dialog/TxConfAdvDialog.h b/src/dialog/TxConfAdvDialog.h index 922abfb7..9122261b 100644 --- a/src/dialog/TxConfAdvDialog.h +++ b/src/dialog/TxConfAdvDialog.h @@ -41,12 +41,15 @@ private: void signedQrCode(); void signedSaveFile(); + void txKeyCopy(); + QScopedPointer ui; QSharedPointer m_ctx; PendingTransaction *m_tx = nullptr; UnsignedTransaction *m_utx = nullptr; QMenu *m_exportUnsignedMenu; QMenu *m_exportSignedMenu; + QMenu *m_exportTxKeyMenu; }; #endif //FEATHER_TXCONFADVDIALOG_H diff --git a/src/dialog/TxConfAdvDialog.ui b/src/dialog/TxConfAdvDialog.ui index 98abf6b9..7030ee12 100644 --- a/src/dialog/TxConfAdvDialog.ui +++ b/src/dialog/TxConfAdvDialog.ui @@ -21,19 +21,30 @@ - - - Transaction ID: - - + + + + + Transaction ID: + + + + + + + txid + + + true + + + + - - - txid - - - true + + + Qt::Horizontal @@ -251,6 +262,16 @@ + + + + Export tx key + + + QToolButton::InstantPopup + + + @@ -272,16 +293,16 @@ - + - Send + Cancel - + - Close + Send From f494f61e24d3aaa4f02b6014e4a51c63c74a5839 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Sat, 14 Aug 2021 17:41:09 +0200 Subject: [PATCH 10/23] WalletInfo: make cache file text selectable --- src/dialog/WalletInfoDialog.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dialog/WalletInfoDialog.ui b/src/dialog/WalletInfoDialog.ui index 9fd06224..aff675d3 100644 --- a/src/dialog/WalletInfoDialog.ui +++ b/src/dialog/WalletInfoDialog.ui @@ -130,6 +130,9 @@ TextLabel + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + From 6cbd81de7b10706f582ba66baec09094569d3330 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Sat, 14 Aug 2021 18:43:45 +0200 Subject: [PATCH 11/23] Settings: add melo.tools and blockchair onion block explorer --- src/SettingsDialog.ui | 10 ++++++++++ src/utils/Utils.cpp | 15 +++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/SettingsDialog.ui b/src/SettingsDialog.ui index 554d5e30..2a2e1521 100644 --- a/src/SettingsDialog.ui +++ b/src/SettingsDialog.ui @@ -413,6 +413,11 @@ xmrchain.net + + + melo.tools + + moneroblocks.info @@ -423,6 +428,11 @@ blockchair.com + + + blkchairbknpn73cfjhevhla7rkp4ed5gg2knctvv7it4lioy22defid.onion + + diff --git a/src/utils/Utils.cpp b/src/utils/Utils.cpp index eb170169..6bbe9580 100644 --- a/src/utils/Utils.cpp +++ b/src/utils/Utils.cpp @@ -357,6 +357,21 @@ QString blockExplorerLink(const QString &blockExplorer, NetworkType::Type nettyp return QString("https://blockchair.com/monero/transaction/%1").arg(txid); } } + else if (blockExplorer == "melo.tools") { + switch (nettype) { + case NetworkType::MAINNET: + return QString("https://melo.tools/explorer/mainnet/tx/%1").arg(txid); + case NetworkType::STAGENET: + return QString("https://melo.tools/explorer/stagenet/tx/%1").arg(txid); + case NetworkType::TESTNET: + return QString("https://melo.tools/explorer/testnet/tx/%1").arg(txid); + } + } + else if (blockExplorer == "blkchairbknpn73cfjhevhla7rkp4ed5gg2knctvv7it4lioy22defid.onion") { + if (nettype == NetworkType::MAINNET) { + return QString("http://blkchairbknpn73cfjhevhla7rkp4ed5gg2knctvv7it4lioy22defid.onion/monero/transaction/%1").arg(txid); + } + } switch (nettype) { case NetworkType::MAINNET: From dd9fd80086ca6a373d33bb915af9559f8513aecc Mon Sep 17 00:00:00 2001 From: tobtoht Date: Sat, 14 Aug 2021 19:43:50 +0200 Subject: [PATCH 12/23] Wizard: cancel after wallet open no longer removes back button --- src/WindowManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WindowManager.cpp b/src/WindowManager.cpp index 8eb203b9..70e34fb3 100644 --- a/src/WindowManager.cpp +++ b/src/WindowManager.cpp @@ -190,7 +190,7 @@ void WindowManager::onWalletOpenPasswordRequired(bool invalidPassword, const QSt case QDialog::Rejected: { m_openWalletTriedOnce = false; - this->showWizard(WalletWizard::Page_OpenWallet); + m_wizard->show(); return; } } From c15426fee40d20cd0988aca9a0b0ad4c93f059f1 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Thu, 19 Aug 2021 19:54:31 +0200 Subject: [PATCH 13/23] Allow .portable.txt for portable mode --- src/utils/Utils.cpp | 2 +- src/utils/config.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/Utils.cpp b/src/utils/Utils.cpp index 6bbe9580..f754c0fb 100644 --- a/src/utils/Utils.cpp +++ b/src/utils/Utils.cpp @@ -100,7 +100,7 @@ bool dirExists(const QString &path) { QString defaultWalletDir() { QString portablePath = QCoreApplication::applicationDirPath().append("/%1"); - if (QFile::exists(portablePath.arg(".portable"))) { + if (QFile::exists(portablePath.arg(".portable")) || QFile::exists(portablePath.arg(".portable.txt"))) { return portablePath.arg("feather_data/wallets"); } diff --git a/src/utils/config.cpp b/src/utils/config.cpp index 2e434ea5..51f17ad2 100644 --- a/src/utils/config.cpp +++ b/src/utils/config.cpp @@ -158,7 +158,7 @@ Config::Config(QObject* parent) QDir Config::defaultConfigDir() { QString portablePath = QCoreApplication::applicationDirPath().append("/%1"); - if (QFile::exists(portablePath.arg(".portable"))) { + if (QFile::exists(portablePath.arg(".portable")) || QFile::exists(portablePath.arg(".portable.txt"))) { return portablePath.arg("feather_data"); } From f2b2bb9b7c63cca3a3d2e40d53fcffc2a31331de Mon Sep 17 00:00:00 2001 From: tobtoht Date: Thu, 19 Aug 2021 20:06:29 +0200 Subject: [PATCH 14/23] History: grab tx key for tx proof dialog --- src/HistoryWidget.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/HistoryWidget.cpp b/src/HistoryWidget.cpp index bf835d13..4499a5d5 100644 --- a/src/HistoryWidget.cpp +++ b/src/HistoryWidget.cpp @@ -144,9 +144,9 @@ void HistoryWidget::createTxProof() { auto *tx = ui->history->currentEntry(); if (!tx) return; - auto *dialog = new TxProofDialog(this, m_ctx, tx); - dialog->exec(); - dialog->deleteLater(); + TxProofDialog dialog{this, m_ctx, tx}; + dialog.getTxKey(); + dialog.exec(); } void HistoryWidget::copy(copyField field) { From 7a467b875ab24ceae9b63e73d965e6c2a3a68f74 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Thu, 19 Aug 2021 20:22:53 +0200 Subject: [PATCH 15/23] Store all constructed transactions in cache --- src/MainWindow.cpp | 55 ++++++++++++++++++------------------- src/dialog/TxConfDialog.cpp | 2 -- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index a7584394..df001c38 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -592,10 +592,8 @@ void MainWindow::onConnectionStatusChanged(int status) } void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QVector &address) { - auto tx_status = tx->status(); QString err{"Can't create transaction: "}; - - if (tx_status != PendingTransaction::Status_Ok){ + if (tx->status() != PendingTransaction::Status_Ok) { QString tx_err = tx->errorString(); qCritical() << tx_err; @@ -615,42 +613,43 @@ void MainWindow::onCreateTransactionSuccess(PendingTransaction *tx, const QVecto qDebug() << Q_FUNC_INFO << err; this->displayWalletErrorMsg(err); m_ctx->wallet->disposeTransaction(tx); + return; } else if (tx->txCount() == 0) { err = QString("%1 %2").arg(err).arg("No unmixable outputs to sweep."); qDebug() << Q_FUNC_INFO << err; this->displayWalletErrorMsg(err); m_ctx->wallet->disposeTransaction(tx); + return; } - else { - const auto &description = m_ctx->tmpTxDescription; - // Show advanced dialog on multi-destination transactions - if (address.size() > 1) { - TxConfAdvDialog dialog_adv{m_ctx, description, this}; - dialog_adv.setTransaction(tx); - dialog_adv.exec(); - return; - } + m_ctx->addCacheTransaction(tx->txid()[0], tx->signedTxToHex(0)); - TxConfDialog dialog{m_ctx, tx, address[0], description, this}; - switch (dialog.exec()) { - case QDialog::Rejected: - { - if (!dialog.showAdvanced) - m_ctx->onCancelTransaction(tx, address); - break; - } - case QDialog::Accepted: - m_ctx->commitTransaction(tx); - break; - } + // Show advanced dialog on multi-destination transactions + if (address.size() > 1) { + TxConfAdvDialog dialog_adv{m_ctx, m_ctx->tmpTxDescription, this}; + dialog_adv.setTransaction(tx); + dialog_adv.exec(); + return; + } - if (dialog.showAdvanced) { - TxConfAdvDialog dialog_adv{m_ctx, description, this}; - dialog_adv.setTransaction(tx); - dialog_adv.exec(); + TxConfDialog dialog{m_ctx, tx, address[0], m_ctx->tmpTxDescription, this}; + switch (dialog.exec()) { + case QDialog::Rejected: + { + if (!dialog.showAdvanced) + m_ctx->onCancelTransaction(tx, address); + break; } + case QDialog::Accepted: + m_ctx->commitTransaction(tx); + break; + } + + if (dialog.showAdvanced) { + TxConfAdvDialog dialog_adv{m_ctx, m_ctx->tmpTxDescription, this}; + dialog_adv.setTransaction(tx); + dialog_adv.exec(); } } diff --git a/src/dialog/TxConfDialog.cpp b/src/dialog/TxConfDialog.cpp index 2d1c4b29..5cb27767 100644 --- a/src/dialog/TxConfDialog.cpp +++ b/src/dialog/TxConfDialog.cpp @@ -72,12 +72,10 @@ TxConfDialog::TxConfDialog(QSharedPointer ctx, PendingTransaction *t ui->label_address->setToolTip("Wallet change/primary address"); } - ui->buttonBox->button(QDialogButtonBox::Ok)->setText("Send"); connect(ui->btn_Advanced, &QPushButton::clicked, this, &TxConfDialog::setShowAdvanced); - m_ctx->addCacheTransaction(tx->txid()[0], tx->signedTxToHex(0)); // Todo: Iterate over all txs this->adjustSize(); } From b452161f19d06ac86b487a1dc9cbcb9390911f90 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Thu, 19 Aug 2021 20:25:51 +0200 Subject: [PATCH 16/23] Nodelist: remove dead nodes --- src/assets/nodes.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/assets/nodes.json b/src/assets/nodes.json index 9cc66ce2..e95c3f53 100644 --- a/src/assets/nodes.json +++ b/src/assets/nodes.json @@ -1,10 +1,8 @@ { "mainnet": { "tor": [ - "monero26mmldsallmxok2kwamne4ve3mybvvn2yijsvss7ey63hc4yyd.onion:18081", "mxcd4577fldb3ppzy7obmmhnu3tf57gbcbd4qhwr2kxyjj2qi3dnbfqd.onion:18081", "moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion:18089", - "3hvpnd4xejtzcuowvru2wfjum5wjf7synigm44rrizr3k4v5vzam2bad.onion:18081", "rbpgdckle3h3vi4wwwrh75usqtoc5r3alohy7yyx57isynvay63nacyd.onion:18089", "6dsdenp6vjkvqzy4wzsnzn6wixkdzihx3khiumyzieauxuxslmcaeiad.onion:18081", "56wl7y2ebhamkkiza4b7il4mrzwtyvpdym7bm2bkg3jrei2je646k3qd.onion:18089", From 170186687a7b236e33f8aef2a8c79c52409b1940 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Mon, 30 Aug 2021 01:58:12 +0200 Subject: [PATCH 17/23] Rebase to Monero v0.17.2.3 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ce756700..a584f3f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ if(DEBUG) set(CMAKE_VERBOSE_MAKEFILE ON) endif() -set(MONERO_HEAD "25ec90f4ddeb19c31553f0104a18d80974f9acb8") +set(MONERO_HEAD "13fa706d276fb896a7221b5580cf61a04b59ed0e") set(BUILD_GUI_DEPS ON) option(ARCH "Target architecture" "x86-64") set(BUILD_64 ON) From 63438d8b829bd49821a45ac7dde76e8240cd715e Mon Sep 17 00:00:00 2001 From: tobtoht Date: Mon, 30 Aug 2021 15:08:06 +0200 Subject: [PATCH 18/23] Update OpenSSL to 1.1.1l --- Dockerfile.linux | 4 ++-- Dockerfile.windows | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Dockerfile.linux b/Dockerfile.linux index 9fbb7a46..ffd91355 100644 --- a/Dockerfile.linux +++ b/Dockerfile.linux @@ -28,9 +28,9 @@ RUN bash verify-packages.sh && \ # OpenSSL: Required for CMake, Qt 5.15.2, libwallet, Tor ENV OPENSSL_ROOT_DIR=/usr/local/openssl/ -RUN git clone -b OpenSSL_1_1_1k --depth 1 https://github.com/openssl/openssl.git && \ +RUN git clone -b OpenSSL_1_1_1l --depth 1 https://github.com/openssl/openssl.git && \ cd openssl && \ - git reset --hard fd78df59b0f656aefe96e39533130454aa957c00 && \ + git reset --hard fb047ebc87b18bdc4cf9ddee9ee1f5ed93e56aff && \ ./config no-shared no-dso --prefix=/usr/local/openssl && \ make -j$THREADS && \ make -j$THREADS install_sw && \ diff --git a/Dockerfile.windows b/Dockerfile.windows index 8ee99921..31f1dbb0 100644 --- a/Dockerfile.windows +++ b/Dockerfile.windows @@ -131,11 +131,11 @@ RUN wget https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.16.tar.gz && \ rm -rf $(pwd) # OpenSSL -> Tor -RUN wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz && \ - echo "892a0875b9872acd04a9fde79b1f943075d5ea162415de3047c327df33fbaee5 openssl-1.1.1k.tar.gz" | sha256sum -c && \ - tar -xzf openssl-1.1.1k.tar.gz && \ - rm openssl-1.1.1k.tar.gz && \ - cd openssl-1.1.1k && \ +RUN wget https://www.openssl.org/source/openssl-1.1.1l.tar.gz && \ + echo "0b7a3e5e59c34827fe0c3a74b7ec8baef302b98fa80088d7f9153aa16fa76bd1 openssl-1.1.1l.tar.gz" | sha256sum -c && \ + tar -xzf openssl-1.1.1l.tar.gz && \ + rm openssl-1.1.1l.tar.gz && \ + cd openssl-1.1.1l && \ ./Configure mingw64 no-shared no-dso --cross-compile-prefix=x86_64-w64-mingw32- --prefix=/usr/local/openssl && \ make -j$THREADS && \ make -j$THREADS install_sw && \ From 1d691d1eb1ca519fb0ab04b075455d50c1328079 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Mon, 30 Aug 2021 15:38:28 +0200 Subject: [PATCH 19/23] Update restore heights --- contrib/generate-restore-heights/heights.py | 46 +++++++ src/assets/restore_heights_monero_mainnet.txt | 116 +++++++++++++++++- .../restore_heights_monero_stagenet.txt | 79 +++++++++++- 3 files changed, 239 insertions(+), 2 deletions(-) create mode 100644 contrib/generate-restore-heights/heights.py diff --git a/contrib/generate-restore-heights/heights.py b/contrib/generate-restore-heights/heights.py new file mode 100644 index 00000000..15f8010c --- /dev/null +++ b/contrib/generate-restore-heights/heights.py @@ -0,0 +1,46 @@ +import requests +import argparse + +parser = argparse.ArgumentParser(description='Generate restore height list.') +parser.add_argument('-P', '--port', + default='18081', + dest='port', + help='Daemon port', + type=int) + +args = parser.parse_args() + +DAEMON_ADDRESS = f"http://127.0.0.1:{args.port}" + +def get_block_timestamp(height: int): + data = { + "jsonrpc": "2.0", + "id": "0", + "method": "get_block_header_by_height", + "params": { + "height": height + } + } + res = requests.get(DAEMON_ADDRESS+"/json_rpc", json=data) + return res.json()['result']['block_header']['timestamp'] + + +def get_height(): + data = { + "jsonrpc": "2.0", + "id": "0", + "method": "get_block_count" + } + res = requests.get(DAEMON_ADDRESS+"/json_rpc", json=data) + return res.json()['result']['count'] + + +timestamps = {} +current_height = get_height() + +timestamps[1] = get_block_timestamp(1) +for height in range(1500, current_height, 1500): + timestamps[height] = get_block_timestamp(height) + +for val in timestamps: + print(f"{timestamps[val]}:{val}") \ No newline at end of file diff --git a/src/assets/restore_heights_monero_mainnet.txt b/src/assets/restore_heights_monero_mainnet.txt index 345106d5..6a4f7cb0 100644 --- a/src/assets/restore_heights_monero_mainnet.txt +++ b/src/assets/restore_heights_monero_mainnet.txt @@ -1509,4 +1509,118 @@ 1609151786:2262000 1609331787:2263500 1609513572:2265000 -1609692129:2266500 \ No newline at end of file +1609692129:2266500 +1609867599:2268000 +1610047219:2269500 +1610228186:2271000 +1610407595:2272500 +1610589258:2274000 +1610772298:2275500 +1610951384:2277000 +1611133107:2278500 +1611312080:2280000 +1611490215:2281500 +1611673294:2283000 +1611853050:2284500 +1612029885:2286000 +1612206719:2287500 +1612387526:2289000 +1612569532:2290500 +1612750081:2292000 +1612930978:2293500 +1613113853:2295000 +1613289586:2296500 +1613470569:2298000 +1613650566:2299500 +1613830056:2301000 +1614009139:2302500 +1614188174:2304000 +1614364622:2305500 +1614547318:2307000 +1614725907:2308500 +1614906615:2310000 +1615094144:2311500 +1615272359:2313000 +1615451290:2314500 +1615629691:2316000 +1615805209:2317500 +1615991354:2319000 +1616169054:2320500 +1616349055:2322000 +1616525847:2323500 +1616708533:2325000 +1616893535:2326500 +1617071845:2328000 +1617249163:2329500 +1617430317:2331000 +1617607600:2332500 +1617790288:2334000 +1617973699:2335500 +1618147282:2337000 +1618329866:2338500 +1618511460:2340000 +1618685970:2341500 +1618865550:2343000 +1619048569:2344500 +1619230022:2346000 +1619407133:2347500 +1619590095:2349000 +1619769449:2350500 +1619948697:2352000 +1620131734:2353500 +1620308138:2355000 +1620490090:2356500 +1620668363:2358000 +1620849947:2359500 +1621033633:2361000 +1621207215:2362500 +1621393360:2364000 +1621567773:2365500 +1621750649:2367000 +1621933277:2368500 +1622108971:2370000 +1622288557:2371500 +1622467139:2373000 +1622651471:2374500 +1622833171:2376000 +1623011441:2377500 +1623188483:2379000 +1623370163:2380500 +1623550839:2382000 +1623728565:2383500 +1623910801:2385000 +1624094652:2386500 +1624268730:2388000 +1624454173:2389500 +1624633102:2391000 +1624813544:2392500 +1624995509:2394000 +1625174760:2395500 +1625350875:2397000 +1625530310:2398500 +1625715884:2400000 +1625890512:2401500 +1626080398:2403000 +1626251832:2404500 +1626434873:2406000 +1626616459:2407500 +1626797788:2409000 +1626976609:2410500 +1627159689:2412000 +1627336518:2413500 +1627515996:2415000 +1627696970:2416500 +1627873363:2418000 +1628056769:2419500 +1628233063:2421000 +1628413022:2422500 +1628596304:2424000 +1628777705:2425500 +1628957276:2427000 +1629135964:2428500 +1629318052:2430000 +1629495981:2431500 +1629677343:2433000 +1629854603:2434500 +1630032622:2436000 +1630217808:2437500 \ No newline at end of file diff --git a/src/assets/restore_heights_monero_stagenet.txt b/src/assets/restore_heights_monero_stagenet.txt index 4525fec9..faf9e359 100644 --- a/src/assets/restore_heights_monero_stagenet.txt +++ b/src/assets/restore_heights_monero_stagenet.txt @@ -528,4 +528,81 @@ 1615573554:790500 1615731420:792000 1615933315:793500 -1616104918:795000 \ No newline at end of file +1616104918:795000 +1616280486:796500 +1616483958:798000 +1616677488:799500 +1616864492:801000 +1617011783:802500 +1617243009:804000 +1617434167:805500 +1617609667:807000 +1617795845:808500 +1617993128:810000 +1618181526:811500 +1618362660:813000 +1618537048:814500 +1618700152:816000 +1618891334:817500 +1619058998:819000 +1619232663:820500 +1619427622:822000 +1619628127:823500 +1619863363:825000 +1619998315:826500 +1620216657:828000 +1620416386:829500 +1620602417:831000 +1620784230:832500 +1620977670:834000 +1621176309:835500 +1621352150:837000 +1621529837:838500 +1621715183:840000 +1621891016:841500 +1622068671:843000 +1622236700:844500 +1622393818:846000 +1622572603:847500 +1622767566:849000 +1622941282:850500 +1623107663:852000 +1623352063:853500 +1623502520:855000 +1623696345:856500 +1623903078:858000 +1624067589:859500 +1624277066:861000 +1624466865:862500 +1624643841:864000 +1624818125:865500 +1625006084:867000 +1625182383:868500 +1625348128:870000 +1625542485:871500 +1625690595:873000 +1625875030:874500 +1626049431:876000 +1626230916:877500 +1626454343:879000 +1626627856:880500 +1626839863:882000 +1627022662:883500 +1627206043:885000 +1627390139:886500 +1627549087:888000 +1627727762:889500 +1627910975:891000 +1628095914:892500 +1628304203:894000 +1628485223:895500 +1628636024:897000 +1628850117:898500 +1629035762:900000 +1629206719:901500 +1629395524:903000 +1629579720:904500 +1629754526:906000 +1629907575:907500 +1630095527:909000 +1630287335:910500 \ No newline at end of file From 2ce6a80fba431c8ad57497c7dbf77d2b0c3b3883 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Sun, 5 Sep 2021 15:22:06 +0200 Subject: [PATCH 20/23] Support all seed languages for 25 word seeds --- src/WindowManager.cpp | 2 +- src/WindowManager.h | 2 +- src/assets.qrc | 1 - src/assets/mnemonic_25_english.txt | 1626 -------------------------- src/wizard/PageWalletRestoreSeed.cpp | 45 +- src/wizard/PageWalletRestoreSeed.h | 7 +- src/wizard/PageWalletRestoreSeed.ui | 12 + src/wizard/WalletWizard.cpp | 2 +- src/wizard/WalletWizard.h | 4 +- 9 files changed, 55 insertions(+), 1646 deletions(-) delete mode 100644 src/assets/mnemonic_25_english.txt diff --git a/src/WindowManager.cpp b/src/WindowManager.cpp index 70e34fb3..c4c6025e 100644 --- a/src/WindowManager.cpp +++ b/src/WindowManager.cpp @@ -212,7 +212,7 @@ bool WindowManager::autoOpenWallet() { // ######################## WALLET CREATION ######################## -void WindowManager::tryCreateWallet(FeatherSeed seed, const QString &path, const QString &password, +void WindowManager::tryCreateWallet(FeatherSeed seed, const QString &path, const QString &password, const QString &seedLanguage, const QString &seedOffset) { if(Utils::fileExists(path)) { auto err = QString("Failed to write wallet to path: \"%1\"; file already exists.").arg(path); diff --git a/src/WindowManager.h b/src/WindowManager.h index bcba0a6c..0fea535a 100644 --- a/src/WindowManager.h +++ b/src/WindowManager.h @@ -45,7 +45,7 @@ private slots: void onWalletPassphraseNeeded(bool on_device); private: - void tryCreateWallet(FeatherSeed seed, const QString &path, const QString &password, const QString &seedOffset); + void tryCreateWallet(FeatherSeed seed, const QString &path, const QString &password, const QString &seedLanguage, const QString &seedOffset); void tryCreateWalletFromDevice(const QString &path, const QString &password, const QString &deviceName, int restoreHeight); void tryCreateWalletFromKeys(const QString &path, const QString &password, const QString &address, const QString &viewkey, const QString &spendkey, quint64 restoreHeight); diff --git a/src/assets.qrc b/src/assets.qrc index 4e813206..c2512404 100644 --- a/src/assets.qrc +++ b/src/assets.qrc @@ -119,7 +119,6 @@ assets/images/xmrig.ico assets/images/xmrig.svg assets/images/zoom.png - assets/mnemonic_25_english.txt assets/restore_heights_monero_mainnet.txt assets/restore_heights_monero_stagenet.txt diff --git a/src/assets/mnemonic_25_english.txt b/src/assets/mnemonic_25_english.txt deleted file mode 100644 index 9b92e934..00000000 --- a/src/assets/mnemonic_25_english.txt +++ /dev/null @@ -1,1626 +0,0 @@ -abbey -abducts -ability -ablaze -abnormal -abort -abrasive -absorb -abyss -academy -aces -aching -acidic -acoustic -acquire -across -actress -acumen -adapt -addicted -adept -adhesive -adjust -adopt -adrenalin -adult -adventure -aerial -afar -affair -afield -afloat -afoot -afraid -after -against -agenda -aggravate -agile -aglow -agnostic -agony -agreed -ahead -aided -ailments -aimless -airport -aisle -ajar -akin -alarms -album -alchemy -alerts -algebra -alkaline -alley -almost -aloof -alpine -already -also -altitude -alumni -always -amaze -ambush -amended -amidst -ammo -amnesty -among -amply -amused -anchor -android -anecdote -angled -ankle -annoyed -answers -antics -anvil -anxiety -anybody -apart -apex -aphid -aplomb -apology -apply -apricot -aptitude -aquarium -arbitrary -archer -ardent -arena -argue -arises -army -around -arrow -arsenic -artistic -ascend -ashtray -aside -asked -asleep -aspire -assorted -asylum -athlete -atlas -atom -atrium -attire -auburn -auctions -audio -august -aunt -austere -autumn -avatar -avidly -avoid -awakened -awesome -awful -awkward -awning -awoken -axes -axis -axle -aztec -azure -baby -bacon -badge -baffles -bagpipe -bailed -bakery -balding -bamboo -banjo -baptism -basin -batch -bawled -bays -because -beer -befit -begun -behind -being -below -bemused -benches -berries -bested -betting -bevel -beware -beyond -bias -bicycle -bids -bifocals -biggest -bikini -bimonthly -binocular -biology -biplane -birth -biscuit -bite -biweekly -blender -blip -bluntly -boat -bobsled -bodies -bogeys -boil -boldly -bomb -border -boss -both -bounced -bovine -bowling -boxes -boyfriend -broken -brunt -bubble -buckets -budget -buffet -bugs -building -bulb -bumper -bunch -business -butter -buying -buzzer -bygones -byline -bypass -cabin -cactus -cadets -cafe -cage -cajun -cake -calamity -camp -candy -casket -catch -cause -cavernous -cease -cedar -ceiling -cell -cement -cent -certain -chlorine -chrome -cider -cigar -cinema -circle -cistern -citadel -civilian -claim -click -clue -coal -cobra -cocoa -code -coexist -coffee -cogs -cohesive -coils -colony -comb -cool -copy -corrode -costume -cottage -cousin -cowl -criminal -cube -cucumber -cuddled -cuffs -cuisine -cunning -cupcake -custom -cycling -cylinder -cynical -dabbing -dads -daft -dagger -daily -damp -dangerous -dapper -darted -dash -dating -dauntless -dawn -daytime -dazed -debut -decay -dedicated -deepest -deftly -degrees -dehydrate -deity -dejected -delayed -demonstrate -dented -deodorant -depth -desk -devoid -dewdrop -dexterity -dialect -dice -diet -different -digit -dilute -dime -dinner -diode -diplomat -directed -distance -ditch -divers -dizzy -doctor -dodge -does -dogs -doing -dolphin -domestic -donuts -doorway -dormant -dosage -dotted -double -dove -down -dozen -dreams -drinks -drowning -drunk -drying -dual -dubbed -duckling -dude -duets -duke -dullness -dummy -dunes -duplex -duration -dusted -duties -dwarf -dwelt -dwindling -dying -dynamite -dyslexic -each -eagle -earth -easy -eating -eavesdrop -eccentric -echo -eclipse -economics -ecstatic -eden -edgy -edited -educated -eels -efficient -eggs -egotistic -eight -either -eject -elapse -elbow -eldest -eleven -elite -elope -else -eluded -emails -ember -emerge -emit -emotion -empty -emulate -energy -enforce -enhanced -enigma -enjoy -enlist -enmity -enough -enraged -ensign -entrance -envy -epoxy -equip -erase -erected -erosion -error -eskimos -espionage -essential -estate -etched -eternal -ethics -etiquette -evaluate -evenings -evicted -evolved -examine -excess -exhale -exit -exotic -exquisite -extra -exult -fabrics -factual -fading -fainted -faked -fall -family -fancy -farming -fatal -faulty -fawns -faxed -fazed -feast -february -federal -feel -feline -females -fences -ferry -festival -fetches -fever -fewest -fiat -fibula -fictional -fidget -fierce -fifteen -fight -films -firm -fishing -fitting -five -fixate -fizzle -fleet -flippant -flying -foamy -focus -foes -foggy -foiled -folding -fonts -foolish -fossil -fountain -fowls -foxes -foyer -framed -friendly -frown -fruit -frying -fudge -fuel -fugitive -fully -fuming -fungal -furnished -fuselage -future -fuzzy -gables -gadget -gags -gained -galaxy -gambit -gang -gasp -gather -gauze -gave -gawk -gaze -gearbox -gecko -geek -gels -gemstone -general -geometry -germs -gesture -getting -geyser -ghetto -ghost -giant -giddy -gifts -gigantic -gills -gimmick -ginger -girth -giving -glass -gleeful -glide -gnaw -gnome -goat -goblet -godfather -goes -goggles -going -goldfish -gone -goodbye -gopher -gorilla -gossip -gotten -gourmet -governing -gown -greater -grunt -guarded -guest -guide -gulp -gumball -guru -gusts -gutter -guys -gymnast -gypsy -gyrate -habitat -hacksaw -haggled -hairy -hamburger -happens -hashing -hatchet -haunted -having -hawk -haystack -hazard -hectare -hedgehog -heels -hefty -height -hemlock -hence -heron -hesitate -hexagon -hickory -hiding -highway -hijack -hiker -hills -himself -hinder -hippo -hire -history -hitched -hive -hoax -hobby -hockey -hoisting -hold -honked -hookup -hope -hornet -hospital -hotel -hounded -hover -howls -hubcaps -huddle -huge -hull -humid -hunter -hurried -husband -huts -hybrid -hydrogen -hyper -iceberg -icing -icon -identity -idiom -idled -idols -igloo -ignore -iguana -illness -imagine -imbalance -imitate -impel -inactive -inbound -incur -industrial -inexact -inflamed -ingested -initiate -injury -inkling -inline -inmate -innocent -inorganic -input -inquest -inroads -insult -intended -inundate -invoke -inwardly -ionic -irate -iris -irony -irritate -island -isolated -issued -italics -itches -items -itinerary -itself -ivory -jabbed -jackets -jaded -jagged -jailed -jamming -january -jargon -jaunt -javelin -jaws -jazz -jeans -jeers -jellyfish -jeopardy -jerseys -jester -jetting -jewels -jigsaw -jingle -jittery -jive -jobs -jockey -jogger -joining -joking -jolted -jostle -journal -joyous -jubilee -judge -juggled -juicy -jukebox -july -jump -junk -jury -justice -juvenile -kangaroo -karate -keep -kennel -kept -kernels -kettle -keyboard -kickoff -kidneys -king -kiosk -kisses -kitchens -kiwi -knapsack -knee -knife -knowledge -knuckle -koala -laboratory -ladder -lagoon -lair -lakes -lamb -language -laptop -large -last -later -launching -lava -lawsuit -layout -lazy -lectures -ledge -leech -left -legion -leisure -lemon -lending -leopard -lesson -lettuce -lexicon -liar -library -licks -lids -lied -lifestyle -light -likewise -lilac -limits -linen -lion -lipstick -liquid -listen -lively -loaded -lobster -locker -lodge -lofty -logic -loincloth -long -looking -lopped -lordship -losing -lottery -loudly -love -lower -loyal -lucky -luggage -lukewarm -lullaby -lumber -lunar -lurk -lush -luxury -lymph -lynx -lyrics -macro -madness -magically -mailed -major -makeup -malady -mammal -maps -masterful -match -maul -maverick -maximum -mayor -maze -meant -mechanic -medicate -meeting -megabyte -melting -memoir -menu -merger -mesh -metro -mews -mice -midst -mighty -mime -mirror -misery -mittens -mixture -moat -mobile -mocked -mohawk -moisture -molten -moment -money -moon -mops -morsel -mostly -motherly -mouth -movement -mowing -much -muddy -muffin -mugged -mullet -mumble -mundane -muppet -mural -musical -muzzle -myriad -mystery -myth -nabbing -nagged -nail -names -nanny -napkin -narrate -nasty -natural -nautical -navy -nearby -necklace -needed -negative -neither -neon -nephew -nerves -nestle -network -neutral -never -newt -nexus -nibs -niche -niece -nifty -nightly -nimbly -nineteen -nirvana -nitrogen -nobody -nocturnal -nodes -noises -nomad -noodles -northern -nostril -noted -nouns -novelty -nowhere -nozzle -nuance -nucleus -nudged -nugget -nuisance -null -number -nuns -nurse -nutshell -nylon -oaks -oars -oasis -oatmeal -obedient -object -obliged -obnoxious -observant -obtains -obvious -occur -ocean -october -odds -odometer -offend -often -oilfield -ointment -okay -older -olive -olympics -omega -omission -omnibus -onboard -oncoming -oneself -ongoing -onion -online -onslaught -onto -onward -oozed -opacity -opened -opposite -optical -opus -orange -orbit -orchid -orders -organs -origin -ornament -orphans -oscar -ostrich -otherwise -otter -ouch -ought -ounce -ourselves -oust -outbreak -oval -oven -owed -owls -owner -oxidant -oxygen -oyster -ozone -pact -paddles -pager -pairing -palace -pamphlet -pancakes -paper -paradise -pastry -patio -pause -pavements -pawnshop -payment -peaches -pebbles -peculiar -pedantic -peeled -pegs -pelican -pencil -people -pepper -perfect -pests -petals -phase -pheasants -phone -phrases -physics -piano -picked -pierce -pigment -piloted -pimple -pinched -pioneer -pipeline -pirate -pistons -pitched -pivot -pixels -pizza -playful -pledge -pliers -plotting -plus -plywood -poaching -pockets -podcast -poetry -point -poker -polar -ponies -pool -popular -portents -possible -potato -pouch -poverty -powder -pram -present -pride -problems -pruned -prying -psychic -public -puck -puddle -puffin -pulp -pumpkins -punch -puppy -purged -push -putty -puzzled -pylons -pyramid -python -queen -quick -quote -rabbits -racetrack -radar -rafts -rage -railway -raking -rally -ramped -randomly -rapid -rarest -rash -rated -ravine -rays -razor -react -rebel -recipe -reduce -reef -refer -regular -reheat -reinvest -rejoices -rekindle -relic -remedy -renting -reorder -repent -request -reruns -rest -return -reunion -revamp -rewind -rhino -rhythm -ribbon -richly -ridges -rift -rigid -rims -ringing -riots -ripped -rising -ritual -river -roared -robot -rockets -rodent -rogue -roles -romance -roomy -roped -roster -rotate -rounded -rover -rowboat -royal -ruby -rudely -ruffled -rugged -ruined -ruling -rumble -runway -rural -rustled -ruthless -sabotage -sack -sadness -safety -saga -sailor -sake -salads -sample -sanity -sapling -sarcasm -sash -satin -saucepan -saved -sawmill -saxophone -sayings -scamper -scenic -school -science -scoop -scrub -scuba -seasons -second -sedan -seeded -segments -seismic -selfish -semifinal -sensible -september -sequence -serving -session -setup -seventh -sewage -shackles -shelter -shipped -shocking -shrugged -shuffled -shyness -siblings -sickness -sidekick -sieve -sifting -sighting -silk -simplest -sincerely -sipped -siren -situated -sixteen -sizes -skater -skew -skirting -skulls -skydive -slackens -sleepless -slid -slower -slug -smash -smelting -smidgen -smog -smuggled -snake -sneeze -sniff -snout -snug -soapy -sober -soccer -soda -software -soggy -soil -solved -somewhere -sonic -soothe -soprano -sorry -southern -sovereign -sowed -soya -space -speedy -sphere -spiders -splendid -spout -sprig -spud -spying -square -stacking -stellar -stick -stockpile -strained -stunning -stylishly -subtly -succeed -suddenly -suede -suffice -sugar -suitcase -sulking -summon -sunken -superior -surfer -sushi -suture -swagger -swept -swiftly -sword -swung -syllabus -symptoms -syndrome -syringe -system -taboo -tacit -tadpoles -tagged -tail -taken -talent -tamper -tanks -tapestry -tarnished -tasked -tattoo -taunts -tavern -tawny -taxi -teardrop -technical -tedious -teeming -tell -template -tender -tepid -tequila -terminal -testing -tether -textbook -thaw -theatrics -thirsty -thorn -threaten -thumbs -thwart -ticket -tidy -tiers -tiger -tilt -timber -tinted -tipsy -tirade -tissue -titans -toaster -tobacco -today -toenail -toffee -together -toilet -token -tolerant -tomorrow -tonic -toolbox -topic -torch -tossed -total -touchy -towel -toxic -toyed -trash -trendy -tribal -trolling -truth -trying -tsunami -tubes -tucks -tudor -tuesday -tufts -tugs -tuition -tulips -tumbling -tunnel -turnip -tusks -tutor -tuxedo -twang -tweezers -twice -twofold -tycoon -typist -tyrant -ugly -ulcers -ultimate -umbrella -umpire -unafraid -unbending -uncle -under -uneven -unfit -ungainly -unhappy -union -unjustly -unknown -unlikely -unmask -unnoticed -unopened -unplugs -unquoted -unrest -unsafe -until -unusual -unveil -unwind -unzip -upbeat -upcoming -update -upgrade -uphill -upkeep -upload -upon -upper -upright -upstairs -uptight -upwards -urban -urchins -urgent -usage -useful -usher -using -usual -utensils -utility -utmost -utopia -uttered -vacation -vague -vain -value -vampire -vane -vapidly -vary -vastness -vats -vaults -vector -veered -vegan -vehicle -vein -velvet -venomous -verification -vessel -veteran -vexed -vials -vibrate -victim -video -viewpoint -vigilant -viking -village -vinegar -violin -vipers -virtual -visited -vitals -vivid -vixen -vocal -vogue -voice -volcano -vortex -voted -voucher -vowels -voyage -vulture -wade -waffle -wagtail -waist -waking -wallets -wanted -warped -washing -water -waveform -waxing -wayside -weavers -website -wedge -weekday -weird -welders -went -wept -were -western -wetsuit -whale -when -whipped -whole -wickets -width -wield -wife -wiggle -wildly -winter -wipeout -wiring -wise -withdrawn -wives -wizard -wobbly -woes -woken -wolf -womanly -wonders -woozy -worry -wounded -woven -wrap -wrist -wrong -yacht -yahoo -yanks -yard -yawning -yearbook -yellow -yesterday -yeti -yields -yodel -yoga -younger -yoyo -zapped -zeal -zebra -zero -zesty -zigzags -zinger -zippers -zodiac -zombie -zones -zoom \ No newline at end of file diff --git a/src/wizard/PageWalletRestoreSeed.cpp b/src/wizard/PageWalletRestoreSeed.cpp index f9128560..db94b3fc 100644 --- a/src/wizard/PageWalletRestoreSeed.cpp +++ b/src/wizard/PageWalletRestoreSeed.cpp @@ -12,13 +12,27 @@ #include "utils/FeatherSeed.h" #include "constants.h" +#include + PageWalletRestoreSeed::PageWalletRestoreSeed(WizardFields *fields, QWidget *parent) : QWizardPage(parent) , ui(new Ui::PageWalletRestoreSeed) , m_fields(fields) { ui->setupUi(this); - ui->label_errorString->hide(); + + std::vector wordlists = crypto::ElectrumWords::get_language_list(); + for (const auto& wordlist: wordlists) { + QStringList words_qt; + std::vector words_std = wordlist->get_word_list(); + for (const auto& word: words_std) { + words_qt += QString::fromStdString(word); + } + + QString language = QString::fromStdString(wordlist->get_english_language_name()); + ui->combo_seedLanguage->addItem(language); + m_wordlists[language] = words_qt; + } QStringList bip39English; for (int i = 0; i != 2048; i++) @@ -27,26 +41,18 @@ PageWalletRestoreSeed::PageWalletRestoreSeed(WizardFields *fields, QWidget *pare // (illegible word with a known location). This can be tested by replacing a word with xxxx bip39English << "xxxx"; - QByteArray data = Utils::fileOpen(":/assets/mnemonic_25_english.txt"); - QStringList moneroEnglish; - for (const auto &seed_word: data.split('\n')) - moneroEnglish << seed_word; - m_tevador.length = 14; m_tevador.setWords(bip39English); m_legacy.length = 25; - m_legacy.setWords(moneroEnglish); + m_legacy.setWords(m_wordlists["English"]); + ui->combo_seedLanguage->setCurrentText("English"); ui->seedEdit->setAcceptRichText(false); ui->seedEdit->setMaximumHeight(150); -#ifndef QT_NO_CURSOR - QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - QGuiApplication::restoreOverrideCursor(); -#endif - connect(ui->seedBtnGroup, QOverload::of(&QButtonGroup::buttonClicked), this, &PageWalletRestoreSeed::onSeedTypeToggled); + connect(ui->combo_seedLanguage, &QComboBox::currentTextChanged, this, &PageWalletRestoreSeed::onSeedLanguageChanged); this->onSeedTypeToggled(); } @@ -56,11 +62,13 @@ void PageWalletRestoreSeed::onSeedTypeToggled() { m_mode = &m_tevador; m_fields->seedType = SeedType::TEVADOR; ui->seedEdit->setPlaceholderText("Enter 14 word seed.."); + ui->group_seedLanguage->hide(); } else if (ui->radio25->isChecked()) { m_mode = &m_legacy; m_fields->seedType = SeedType::MONERO; ui->seedEdit->setPlaceholderText("Enter 25 word seed.."); + ui->group_seedLanguage->show(); } ui->label_errorString->hide(); @@ -69,6 +77,11 @@ void PageWalletRestoreSeed::onSeedTypeToggled() { ui->seedEdit->setText(""); } +void PageWalletRestoreSeed::onSeedLanguageChanged(const QString &language) { + m_legacy.setWords(m_wordlists[language]); + m_fields->seedLanguage = language; +} + int PageWalletRestoreSeed::nextId() const { if (m_mode == &m_legacy) { return WalletWizard::Page_SetRestoreHeight; @@ -100,8 +113,14 @@ bool PageWalletRestoreSeed::validatePage() { return false; } + // libwallet will accept e.g. "brötchen" or "BRÖTCHEN" instead of "Brötchen" + QStringList lowercaseWords; + for (const auto &word : m_mode->words) { + lowercaseWords << word.toLower(); + } + for (const auto &word : seedSplit) { - if (!m_mode->words.contains(word)) { + if (!lowercaseWords.contains(word.toLower())) { ui->label_errorString->show(); ui->label_errorString->setText(QString("Mnemonic seed contains an unknown word: %1").arg(word)); ui->seedEdit->setStyleSheet(errStyle); diff --git a/src/wizard/PageWalletRestoreSeed.h b/src/wizard/PageWalletRestoreSeed.h index f2d89717..2c0ebe40 100644 --- a/src/wizard/PageWalletRestoreSeed.h +++ b/src/wizard/PageWalletRestoreSeed.h @@ -32,8 +32,8 @@ private: seedType() { completer.setModel(&completerModel); - completer.setModelSorting(QCompleter::CaseInsensitivelySortedModel); - completer.setCaseSensitivity(Qt::CaseInsensitive); + completer.setModelSorting(QCompleter::CaseSensitivelySortedModel); + completer.setCaseSensitivity(Qt::CaseSensitive); completer.setWrapAround(false); } @@ -49,6 +49,7 @@ private: }; void onSeedTypeToggled(); + void onSeedLanguageChanged(const QString &language); Ui::PageWalletRestoreSeed *ui; WizardFields *m_fields; @@ -57,6 +58,8 @@ private: seedType m_legacy; seedType *m_mode; + + QMap m_wordlists; }; #endif diff --git a/src/wizard/PageWalletRestoreSeed.ui b/src/wizard/PageWalletRestoreSeed.ui index 7f3f5c5f..3e62d387 100644 --- a/src/wizard/PageWalletRestoreSeed.ui +++ b/src/wizard/PageWalletRestoreSeed.ui @@ -46,6 +46,18 @@ + + + + Select seed language: + + + + + + + + diff --git a/src/wizard/WalletWizard.cpp b/src/wizard/WalletWizard.cpp index 2529ed2a..24782300 100644 --- a/src/wizard/WalletWizard.cpp +++ b/src/wizard/WalletWizard.cpp @@ -127,5 +127,5 @@ void WalletWizard::onCreateWallet() { if (m_wizardFields.mode == WizardMode::RestoreFromSeed && m_wizardFields.seedType == SeedType::MONERO) seed.setRestoreHeight(m_wizardFields.restoreHeight); - emit createWallet(seed, walletPath, m_wizardFields.password, m_wizardFields.seedOffsetPassphrase); + emit createWallet(seed, walletPath, m_wizardFields.password, m_wizardFields.seedLanguage, m_wizardFields.seedOffsetPassphrase); } diff --git a/src/wizard/WalletWizard.h b/src/wizard/WalletWizard.h index 377ea389..d353a6e2 100644 --- a/src/wizard/WalletWizard.h +++ b/src/wizard/WalletWizard.h @@ -12,6 +12,7 @@ #include "model/WalletKeysFilesModel.h" #include "utils/RestoreHeightLookup.h" #include "utils/config.h" +#include "constants.h" enum WizardMode { CreateWallet = 0, @@ -32,6 +33,7 @@ struct WizardFields { QString walletDir; QString seed; QString seedOffsetPassphrase; + QString seedLanguage = constants::seedLanguage; QString password; QString modeText; QString address; @@ -72,7 +74,7 @@ signals: void createWalletFromDevice(const QString &path, const QString &password, const QString &deviceName, int restoreHeight); void createWalletFromKeys(const QString &path, const QString &password, const QString &address, const QString &viewkey, const QString &spendkey, quint64 restoreHeight, bool deterministic = false); - void createWallet(FeatherSeed seed, const QString &path, const QString &password, const QString &seedOffset = ""); + void createWallet(FeatherSeed seed, const QString &path, const QString &password, const QString &seedLanguage, const QString &seedOffset = ""); private slots: void onCreateWallet(); From cb12e416999d7c0dfcc260409864fcdaa1491d04 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Sun, 5 Sep 2021 17:43:57 +0200 Subject: [PATCH 21/23] Wizard: allow enters in seed entry --- src/wizard/PageWalletRestoreSeed.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wizard/PageWalletRestoreSeed.cpp b/src/wizard/PageWalletRestoreSeed.cpp index db94b3fc..bde957da 100644 --- a/src/wizard/PageWalletRestoreSeed.cpp +++ b/src/wizard/PageWalletRestoreSeed.cpp @@ -103,8 +103,8 @@ bool PageWalletRestoreSeed::validatePage() { ui->seedEdit->setStyleSheet(""); auto errStyle = "QTextEdit{border: 1px solid red;}"; - auto seed = ui->seedEdit->toPlainText().replace("\n", "").replace("\r", "").trimmed(); - auto seedSplit = seed.split(" "); + auto seed = ui->seedEdit->toPlainText().replace("\n", " ").replace("\r", "").trimmed(); + QStringList seedSplit = seed.split(" ", Qt::SkipEmptyParts); if (seedSplit.length() != m_mode->length) { ui->label_errorString->show(); @@ -138,7 +138,7 @@ bool PageWalletRestoreSeed::validatePage() { QMessageBox::information(this, "Corrected erasure", QString("xxxx -> %1").arg(_seed.correction)); } - m_fields->seed = seed; + m_fields->seed = seedSplit.join(" "); m_fields->seedOffsetPassphrase = ui->line_seedOffset->text(); return true; From 86574abd94c1448fbf42eca22158b9a5a51cd73c Mon Sep 17 00:00:00 2001 From: tobtoht Date: Sun, 5 Sep 2021 20:13:37 +0200 Subject: [PATCH 22/23] TxImportDialog: check if we have tx, check if tx import was successful --- CMakeLists.txt | 2 +- src/dialog/TxImportDialog.cpp | 12 ++++++++++++ src/libwalletqt/Wallet.cpp | 5 +++++ src/libwalletqt/Wallet.h | 3 +++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a584f3f9..9dc76b96 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ if(DEBUG) set(CMAKE_VERBOSE_MAKEFILE ON) endif() -set(MONERO_HEAD "13fa706d276fb896a7221b5580cf61a04b59ed0e") +set(MONERO_HEAD "d4257af2e7503fc6dc09fc704606230d353a0a02") set(BUILD_GUI_DEPS ON) option(ARCH "Target architecture" "x86-64") set(BUILD_64 ON) diff --git a/src/dialog/TxImportDialog.cpp b/src/dialog/TxImportDialog.cpp index 60cf6ab4..2a00bcc7 100644 --- a/src/dialog/TxImportDialog.cpp +++ b/src/dialog/TxImportDialog.cpp @@ -35,6 +35,14 @@ TxImportDialog::TxImportDialog(QWidget *parent, QSharedPointer ctx) void TxImportDialog::loadTx() { QString txid = ui->line_txid->text(); + + if (m_ctx->wallet->haveTransaction(txid)) { + QMessageBox::warning(this, "Warning", "This transaction already exists in the wallet. " + "If you can't find it in your history, " + "check if it belongs to a different account (Wallet -> Account)"); + return; + } + FeatherNode node = m_ctx->nodes->connection(); if (node.isLocal()) { @@ -94,6 +102,10 @@ void TxImportDialog::onImport() { bool double_spend_seen = tx.value("double_spend_seen").toBool(); if (m_ctx->wallet->importTransaction(tx.value("tx_hash").toString(), output_indices, height, timestamp, false, pool, double_spend_seen)) { + if (!m_ctx->wallet->haveTransaction(txid)) { + QMessageBox::warning(this, "Import transaction", "This transaction does not belong to this wallet."); + return; + } QMessageBox::information(this, "Import transaction", "Transaction imported successfully."); } else { QMessageBox::warning(this, "Import transaction", "Transaction import failed."); diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp index 98d0d9da..f0dd9f38 100644 --- a/src/libwalletqt/Wallet.cpp +++ b/src/libwalletqt/Wallet.cpp @@ -601,6 +601,11 @@ QString Wallet::printScannedPoolTxs() return QString::fromStdString(m_walletImpl->printScannedPoolTxs()); } +bool Wallet::haveTransaction(const QString &txid) +{ + return m_walletImpl->haveTransaction(txid.toStdString()); +} + void Wallet::startRefresh() { m_refreshEnabled = true; diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h index 49e44eb8..1e419450 100644 --- a/src/libwalletqt/Wallet.h +++ b/src/libwalletqt/Wallet.h @@ -246,6 +246,9 @@ public: QString printAddressBook(); QString printScannedPoolTxs(); + //! does wallet have txid + bool haveTransaction(const QString &txid); + //! refreshes the wallet bool refresh(bool historyAndSubaddresses = false); From 7862063361fe730c0507dafa7387a9bd66831a49 Mon Sep 17 00:00:00 2001 From: tobtoht Date: Tue, 7 Sep 2021 17:48:45 +0200 Subject: [PATCH 23/23] Receive: 'Generate subaddress' -> 'Create new address' --- src/ReceiveWidget.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ReceiveWidget.ui b/src/ReceiveWidget.ui index 494b2a57..0d420817 100644 --- a/src/ReceiveWidget.ui +++ b/src/ReceiveWidget.ui @@ -106,7 +106,7 @@ - Generate Subaddress + Create new address