diff --git a/src/Makefile.am b/src/Makefile.am index 38b77b65c0..3f43272474 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -923,6 +923,10 @@ if ENABLE_QT include Makefile.qt.include endif +if ENABLE_QT_TESTS +include Makefile.qttest.include +endif + if ENABLE_TESTS include Makefile.test.include else diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include index ac6c08c3be..613cc3178e 100644 --- a/src/Makefile.qt.include +++ b/src/Makefile.qt.include @@ -517,7 +517,7 @@ endif qt_firo_qt_LDADD += -ltor qt_firo_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) \ - $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBFIRO_SIGMA) $(LIBLELANTUS) $(LIBSPARK)\ + $(LIBBITCOIN_CONSENSUS) $(LIBBITCOIN_CRYPTO) $(LIBFIRO_SIGMA) $(LIBLELANTUS) $(LIBSPARK) \ $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BACKTRACE_LIB) $(BOOST_LIBS) $(QT_LIBS) \ $(QT_DBUS_LIBS) $(QR_LIBS) $(BDB_LIBS) $(SSL_LIBS) \ $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) $(LIBSECP256K1) $(LIBBLSSIG_LIBS) $(LIBBLSSIG_DEPENDS) \ diff --git a/src/Makefile.qttest.include b/src/Makefile.qttest.include index 65a4a8951f..9ff72747da 100644 --- a/src/Makefile.qttest.include +++ b/src/Makefile.qttest.include @@ -8,7 +8,8 @@ TESTS += qt/test/test_bitcoin-qt TEST_QT_MOC_CPP = \ qt/test/moc_compattests.cpp \ qt/test/moc_rpcnestedtests.cpp \ - qt/test/moc_uritests.cpp + qt/test/moc_uritests.cpp \ + qt/test/moc_test_sendcoinsentry.cpp if ENABLE_WALLET TEST_QT_MOC_CPP += @@ -17,7 +18,8 @@ endif TEST_QT_H = \ qt/test/compattests.h \ qt/test/rpcnestedtests.h \ - qt/test/uritests.h + qt/test/uritests.h \ + qt/test/test_sendcoinsentry.h qt_test_test_bitcoin_qt_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(BITCOIN_QT_INCLUDES) \ $(QT_INCLUDES) $(QT_TEST_INCLUDES) @@ -27,6 +29,7 @@ qt_test_test_bitcoin_qt_SOURCES = \ qt/test/rpcnestedtests.cpp \ qt/test/test_main.cpp \ qt/test/uritests.cpp \ + qt/test/test_sendcoinsentry.cpp \ $(TEST_QT_H) if ENABLE_WALLET qt_test_test_bitcoin_qt_SOURCES += @@ -34,7 +37,7 @@ endif nodist_qt_test_test_bitcoin_qt_SOURCES = $(TEST_QT_MOC_CPP) -qt_test_test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER) +qt_test_test_bitcoin_qt_LDADD = $(LIBBITCOINQT) $(LIBBITCOIN_SERVER) $(TOR_LIBS) if ENABLE_WALLET qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_WALLET) endif @@ -43,13 +46,13 @@ qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_ZMQ) $(ZMQ_LIBS) endif qt_test_test_bitcoin_qt_LDADD += $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) \ - $(LIBBITCOIN_UTIL) $(LIBZEROCOIN) $(LIBBITCOIN_CONSENSUS) \ - $(LIBBITCOIN_CRYPTO) $(LIBFIRO_SIGMA) $(LIBLELANTUS) $(LIBUNIVALUE) $(LIBLEVELDB) \ + $(LIBBITCOIN_UTIL) $(LIBZEROCOIN) $(LIBBITCOIN_CONSENSUS) $(LIBBLSSIG_LIBS) $(LIBBLSSIG_DEPENDS) \ + $(LIBBITCOIN_CRYPTO) $(LIBFIRO_SIGMA) $(LIBLELANTUS) $(LIBUNIVALUE) $(LIBSPARK) $(LIBLEVELDB) \ $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(QT_DBUS_LIBS) $(QT_TEST_LIBS) $(QT_LIBS) \ $(QR_LIBS) $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) \ - $(MINIUPNPC_LIBS) $(LIBSECP256K1) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) + $(MINIUPNPC_LIBS) $(LIBSECP256K1) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(BACKTRACE_LIB) -qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +qt_test_test_bitcoin_qt_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(QT_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) $(LDFLAGS_WRAP_EXCEPTIONS) qt_test_test_bitcoin_qt_CXXFLAGS = $(AM_CXXFLAGS) $(QT_PIE_FLAGS) CLEAN_BITCOIN_QT_TEST = $(TEST_QT_MOC_CPP) qt/test/*.gcda qt/test/*.gcno diff --git a/src/libspark/spend_transaction.cpp b/src/libspark/spend_transaction.cpp index acb747c1dc..3e30b64a4c 100644 --- a/src/libspark/spend_transaction.cpp +++ b/src/libspark/spend_transaction.cpp @@ -270,7 +270,7 @@ bool SpendTransaction::verify( if (tx.S1.size() != w || tx.C1.size() != w || tx.T.size() != w || - tx.grootle_proofs.size() != w, + tx.grootle_proofs.size() != w || tx.cover_set_sizes.size() != tx.cover_set_representations.size()) { throw std::invalid_argument("Bad spend transaction semantics"); } diff --git a/src/qt/forms/sendcoinsentry.ui b/src/qt/forms/sendcoinsentry.ui index c5098689c4..361f182f0a 100644 --- a/src/qt/forms/sendcoinsentry.ui +++ b/src/qt/forms/sendcoinsentry.ui @@ -162,7 +162,7 @@ - You are using a transparent transaction, please go private. If this is a masternode transaction, you do not have to go private + color: #FFA800; margin-left:-10px; diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 26cbf138e5..63e4862569 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -394,15 +394,6 @@ void SendCoinsDialog::on_sendButton_clicked() return; } } else if ((fAnonymousMode == false) && (sparkAddressCount == 0)) { - if (spark::IsSparkAllowed()) { - SendGoPrivateDialog goPrivateDialog; - bool clickedButton = goPrivateDialog.getClickedButton(); - if (!clickedButton) { - setAnonymizeMode(true); - fNewRecipientAllowed = true; - return; - } - } prepareStatus = model->prepareTransaction(currentTransaction, &ctrl); } else { fNewRecipientAllowed = true; @@ -428,6 +419,15 @@ void SendCoinsDialog::on_sendButton_clicked() // Format confirmation message QStringList formatted; + QString warningMessage; + + for(int i = 0; i < recipients.size(); ++i) { + warningMessage = entry->generateWarningText(recipients[i].address, fAnonymousMode); + if ((model->validateSparkAddress(recipients[i].address)) || (recipients[i].address.startsWith("EX"))) { + break; + } + } + if ((fAnonymousMode == false) && (recipients.size() == sparkAddressCount) && spark::IsSparkAllowed()) { for(int i = 0; i < recipients.size(); i++) { @@ -530,6 +530,7 @@ void SendCoinsDialog::on_sendButton_clicked() } QString questionString = tr("Are you sure you want to send?"); + questionString.append(warningMessage); questionString.append("

%1"); double txSize; if ((fAnonymousMode == false) && (recipients.size() == sparkAddressCount) && spark::IsSparkAllowed()) @@ -688,9 +689,9 @@ void SendCoinsDialog::on_sendButton_clicked() void SendCoinsDialog::on_switchFundButton_clicked() { setAnonymizeMode(!fAnonymousMode); - coinControlUpdateLabels(); - + entry->setfAnonymousMode(fAnonymousMode); entry->setWarning(fAnonymousMode); + coinControlUpdateLabels(); } void SendCoinsDialog::clear() @@ -719,7 +720,9 @@ SendCoinsEntry *SendCoinsDialog::addEntry() { entry = new SendCoinsEntry(platformStyle, this); entry->setModel(model); + entry->setfAnonymousMode(fAnonymousMode); entry->setWarning(fAnonymousMode); + ui->entries->addWidget(entry); connect(entry, &SendCoinsEntry::removeEntry, this, &SendCoinsDialog::removeEntry); connect(entry, &SendCoinsEntry::payAmountChanged, this, &SendCoinsDialog::coinControlUpdateLabels); @@ -811,7 +814,6 @@ void SendCoinsDialog::setAddress(const QString &address) { entry = addEntry(); } - entry->setAddress(address); } @@ -1339,71 +1341,6 @@ void SendConfirmationDialog::updateYesButton() } } -SendGoPrivateDialog::SendGoPrivateDialog():QMessageBox() -{ - QDialog::setWindowTitle("Make this a private transaction"); - QDialog::setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint); - - QLabel *ic = new QLabel(); - QIcon icon_; - icon_.addFile(QString::fromUtf8(":/icons/ic_info"), QSize(), QIcon::Normal, QIcon::On); - ic->setPixmap(icon_.pixmap(18, 18)); - ic->setFixedWidth(50); - ic->setAlignment(Qt::AlignRight); - ic->setStyleSheet("color:#92400E"); - QLabel *text = new QLabel(); - text->setText(tr("You are using a transparent transaction, please go private. If this is a masternode transaction, you do not have to go private")); - text->setAlignment(Qt::AlignLeft); - text->setWordWrap(true); - text->setStyleSheet("color:#92400E;"); - - QPushButton *ignore = new QPushButton(this); - ignore->setText("Ignore"); - ignore->setStyleSheet("color:#9b1c2e;background-color:none;margin-top:30px;margin-bottom:60px;margin-left:50px;margin-right:20px;border:1px solid #9b1c2e;"); - QPushButton *goPrivate = new QPushButton(this); - goPrivate->setText("Go Private"); - goPrivate->setStyleSheet("margin-top:30px;margin-bottom:60px;margin-left:20px;margin-right:50px;"); - QHBoxLayout *groupButton = new QHBoxLayout(this); - groupButton->addWidget(ignore); - groupButton->addWidget(goPrivate); - - QHBoxLayout *hlayout = new QHBoxLayout(this); - hlayout->addWidget(ic); - hlayout->addWidget(text); - - QWidget *layout_ = new QWidget(); - layout_->setLayout(hlayout); - layout_->setStyleSheet("background-color:#FEF3C7;"); - - QVBoxLayout *vlayout = new QVBoxLayout(this); - vlayout->addWidget(layout_); - vlayout->addLayout(groupButton); - vlayout->setContentsMargins(0,0,0,0); - QWidget *wbody = new QWidget(); - wbody->setLayout(vlayout); - layout()->addWidget(wbody); - setContentsMargins(0, 0, 0, 0); - setStyleSheet("margin-right:-30px;"); - setStandardButtons(0); - connect(ignore, &QPushButton::clicked, this, &SendGoPrivateDialog::onIgnoreClicked); - connect(goPrivate, &QPushButton::clicked, this, &SendGoPrivateDialog::onGoPrivateClicked); - exec(); -} -void SendGoPrivateDialog::onIgnoreClicked() -{ - setVisible(false); - clickedButton = true; -} -void SendGoPrivateDialog::onGoPrivateClicked() -{ - setVisible(false); - clickedButton = false; -} - -bool SendGoPrivateDialog::getClickedButton() -{ - return clickedButton; -} void SendCoinsDialog::resizeEvent(QResizeEvent* event) { QWidget::resizeEvent(event); diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index 5abf2e3a07..b117fafce9 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -130,18 +130,4 @@ private Q_SLOTS: }; -class SendGoPrivateDialog : public QMessageBox -{ - Q_OBJECT -private: - bool clickedButton; -public: - SendGoPrivateDialog(); - bool getClickedButton(); - -private Q_SLOTS: - void onIgnoreClicked(); - void onGoPrivateClicked(); -}; - #endif // BITCOIN_QT_SENDCOINSDIALOG_H diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp index eb2d7e62dc..c250db4d21 100644 --- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -11,6 +11,7 @@ #include "optionsmodel.h" #include "platformstyle.h" #include "walletmodel.h" +#include "../wallet/wallet.h" #include #include @@ -83,6 +84,7 @@ void SendCoinsEntry::on_addressBookButton_clicked() void SendCoinsEntry::on_payTo_textChanged(const QString &address) { updateLabel(address); + setWarning(fAnonymousMode); } void SendCoinsEntry::setModel(WalletModel *_model) @@ -123,15 +125,37 @@ void SendCoinsEntry::deleteClicked() Q_EMIT removeEntry(this); } -void SendCoinsEntry::setWarning(bool fAnonymousMode) +void SendCoinsEntry::setWarning(bool fAnonymousMode) { + const QString address = ui->payTo->text(); + const QString warningText = generateWarningText(address, fAnonymousMode); + const bool hasValidAddress = model->validateAddress(address) || model->validateSparkAddress(address); + ui->textWarning->setText(warningText); + ui->textWarning->setVisible(!warningText.isEmpty() && hasValidAddress); + ui->iconWarning->setVisible(!warningText.isEmpty() && hasValidAddress); +} + +QString SendCoinsEntry::generateWarningText(const QString& address, const bool fAnonymousMode) { - if(fAnonymousMode) { - ui->textWarning->hide(); - ui->iconWarning->hide(); + QString warningText; + + if (address.startsWith("EX")) { + warningText = tr(" You are sending Firo to an Exchange Address. Exchange Addresses can only receive funds from a transparent address."); } else { - ui->textWarning->show(); - ui->iconWarning->show(); + if (!fAnonymousMode) { + if (pwalletMain->validateAddress(address.toStdString())) { + warningText = tr(" You are sending Firo from a transparent address to another transparent address. To protect your privacy, we recommend using Spark addresses instead."); + } else if (pwalletMain->validateSparkAddress(address.toStdString())) { + warningText = tr(" You are sending Firo from a transparent address to a Spark address."); + } + } else { + if (pwalletMain->validateSparkAddress(address.toStdString())) { + warningText = tr(" You are sending Firo from a Spark address to another Spark address. This transaction is fully private."); + } else if (pwalletMain->validateAddress(address.toStdString())) { + warningText = tr(" You are sending Firo from a private Spark pool to a transparent address. Please note that some exchanges do not accept direct Spark deposits."); + } + } } + return warningText; } bool SendCoinsEntry::validate() @@ -231,6 +255,11 @@ bool SendCoinsEntry::isPayToPcode() const return isPcodeEntry; } +void SendCoinsEntry::setfAnonymousMode(bool fAnonymousMode) +{ + this->fAnonymousMode = fAnonymousMode; +} + void SendCoinsEntry::setFocus() { ui->payTo->setFocus(); diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h index 506981d5e3..2e89f0fd5e 100644 --- a/src/qt/sendcoinsentry.h +++ b/src/qt/sendcoinsentry.h @@ -49,7 +49,9 @@ class SendCoinsEntry : public QStackedWidget void setFocus(); void setWarning(bool fAnonymousMode); - + void setfAnonymousMode(bool fAnonymousMode); + static QString generateWarningText(const QString& address, const bool fAnonymousMode); + public Q_SLOTS: void clear(); @@ -71,7 +73,7 @@ private Q_SLOTS: WalletModel *model; const PlatformStyle *platformStyle; bool isPcodeEntry; - + bool fAnonymousMode = false; bool updateLabel(const QString &address); void resizeEvent(QResizeEvent* event) override; void adjustTextSize(int width, int height); diff --git a/src/qt/test/test_main.cpp b/src/qt/test/test_main.cpp index b8f913d3f5..ac8716a22a 100644 --- a/src/qt/test/test_main.cpp +++ b/src/qt/test/test_main.cpp @@ -12,11 +12,9 @@ #include "util.h" #include "uritests.h" #include "compattests.h" - +#include "test_sendcoinsentry.h" #include #include -#include - #include #if defined(QT_STATICPLUGIN) && QT_VERSION < 0x050000 @@ -35,7 +33,7 @@ int main(int argc, char *argv[]) ECC_Start(); SetupEnvironment(); SetupNetworking(); - SelectParams(CBaseChainParams::MAIN); + SelectParams(CBaseChainParams::REGTEST); noui_connect(); bool fInvalid = false; @@ -50,10 +48,15 @@ int main(int argc, char *argv[]) URITests test1; if (QTest::qExec(&test1) != 0) fInvalid = true; - } - RPCNestedTests test3; - if (QTest::qExec(&test3) != 0) + + TestSendCoinsEntry test2; + if (QTest::qExec(&test2) != 0) fInvalid = true; + + // RPCNestedTests test3; + // if (QTest::qExec(&test3) != 0) + // fInvalid = true; + CompatTests test4; if (QTest::qExec(&test4) != 0) fInvalid = true; diff --git a/src/qt/test/test_sendcoinsentry.cpp b/src/qt/test/test_sendcoinsentry.cpp new file mode 100644 index 0000000000..d79e42174e --- /dev/null +++ b/src/qt/test/test_sendcoinsentry.cpp @@ -0,0 +1,10 @@ +#include "test_sendcoinsentry.h" + +void TestSendCoinsEntry::testGenerateWarningText() +{ + QCOMPARE(SendCoinsEntry::generateWarningText("EXRSxX8yJHudk4QswGf3N5aPVTUi5Q1ZdX56", false), QObject::tr(" You are sending Firo to an Exchange Address. Exchange Addresses can only receive funds from a transparent address.")); + QCOMPARE(SendCoinsEntry::generateWarningText("TLyNUvysvUyt2u6vL74NEkB6ed8LTQd3mz", false), QObject::tr(" You are sending Firo from a transparent address to another transparent address. To protect your privacy, we recommend using Spark addresses instead.")); + QCOMPARE(SendCoinsEntry::generateWarningText("sr1ek2uspg2v4qu0lmccrnj90tfkdpp5zmpykr4ffdprqlf0s4devl8n0674s4d4cthxsa5w9p66s5x0zgw982t80xx9uzmxysxuawmupgfa0xecj9shm6pj7l3rshqxqtg94k88fg5u856r", false), QObject::tr(" You are sending Firo from a transparent address to a Spark address.")); + QCOMPARE(SendCoinsEntry::generateWarningText("sr1ek2uspg2v4qu0lmccrnj90tfkdpp5zmpykr4ffdprqlf0s4devl8n0674s4d4cthxsa5w9p66s5x0zgw982t80xx9uzmxysxuawmupgfa0xecj9shm6pj7l3rshqxqtg94k88fg5u856r", true), QObject::tr(" You are sending Firo from a Spark address to another Spark address. This transaction is fully private.")); + QCOMPARE(SendCoinsEntry::generateWarningText("TLyNUvysvUyt2u6vL74NEkB6ed8LTQd3mz", true), QObject::tr(" You are sending Firo from a private Spark pool to a transparent address. Please note that some exchanges do not accept direct Spark deposits.")); +} diff --git a/src/qt/test/test_sendcoinsentry.h b/src/qt/test/test_sendcoinsentry.h new file mode 100644 index 0000000000..8da54b1f3e --- /dev/null +++ b/src/qt/test/test_sendcoinsentry.h @@ -0,0 +1,16 @@ +#ifndef BITCOIN_QT_TEST_SENDCOINSENTRY_H +#define BITCOIN_QT_TEST_SENDCOINSENTRY_H + +#include +#include +#include "sendcoinsentry.h" + +class TestSendCoinsEntry : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void testGenerateWarningText(); +}; + +#endif // BITCOIN_QT_TEST_SENDCOINSENTRY_H \ No newline at end of file diff --git a/src/qt/test/uritests.cpp b/src/qt/test/uritests.cpp index 518ed28a5b..89bf5c548c 100644 --- a/src/qt/test/uritests.cpp +++ b/src/qt/test/uritests.cpp @@ -51,7 +51,7 @@ void URITests::uriTests() QVERIFY(rv.address == QString("MUVz3KZqgJdC3djwVCLD6ZMpDj5X1FqeKs")); QVERIFY(rv.label == QString()); - QVERIFY(GUIUtil::parseBitcoinURI("firo://MUVz3KZqgJdC3djwVCLD6ZMpDj5X1FqeKs?message=Wikipedia Example Address", &rv)); + QVERIFY(GUIUtil::parseBitcoinURI("firo:MUVz3KZqgJdC3djwVCLD6ZMpDj5X1FqeKs?message=Wikipedia Example Address", &rv)); QVERIFY(rv.address == QString("MUVz3KZqgJdC3djwVCLD6ZMpDj5X1FqeKs")); QVERIFY(rv.label == QString());