From 89dda8eebe8b900e856c8d2ffb1c131293577787 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Mon, 22 Oct 2018 22:10:52 -0700 Subject: [PATCH 01/25] Turnstile prototype --- src/mainwindow.cpp | 35 ++++++ src/mainwindow.ui | 12 ++ src/turnstile.ui | 229 +++++++++++++++++++++++++++++++++++++ src/turnstileprogress.ui | 154 +++++++++++++++++++++++++ src/ui_mainwindow.h | 10 ++ src/ui_turnstile.h | 210 ++++++++++++++++++++++++++++++++++ src/ui_turnstileprogress.h | 141 +++++++++++++++++++++++ zcash-qt-wallet.pro | 4 +- 8 files changed, 794 insertions(+), 1 deletion(-) create mode 100644 src/turnstile.ui create mode 100644 src/turnstileprogress.ui create mode 100644 src/ui_turnstile.h create mode 100644 src/ui_turnstileprogress.h diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 28fac81..9249eef 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2,11 +2,14 @@ #include "ui_mainwindow.h" #include "ui_about.h" #include "ui_settings.h" +#include "ui_turnstile.h" +#include "ui_turnstileprogress.h" #include "rpc.h" #include "balancestablemodel.h" #include "settings.h" #include "utils.h" + #include "precompiled.h" @@ -24,6 +27,38 @@ MainWindow::MainWindow(QWidget *parent) : // Settings editor setupSettingsModal(); + // Turnstile migration + QObject::connect(ui->actionTurnstile_Migration, &QAction::triggered, [=] () { + Ui_Turnstile turnstile; + QDialog d(this); + turnstile.setupUi(&d); + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); + turnstile.msgIcon->setPixmap(icon.pixmap(64, 64)); + + turnstile.migrateZaddList->addItem("All Sprout z-Addrs"); + turnstile.migrateTo->addItem("zs1gv64eu0v2wx7raxqxlmj354y9ycznwaau9kduljzczxztvs4qcl00kn2sjxtejvrxnkucw5xx9u"); + turnstile.privLevel->addItem("Good - 3 tx over 3 days"); + turnstile.privLevel->addItem("Excellent - 5 tx over 5 days"); + turnstile.privLevel->addItem("Paranoid - 10 tx over 7 days"); + + turnstile.buttonBox->button(QDialogButtonBox::Ok)->setText("Start"); + + d.exec(); + }); + + QObject::connect(ui->actionProgress, &QAction::triggered, [=] () { + Ui_TurnstileProgress progress; + QDialog d(this); + progress.setupUi(&d); + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning); + progress.msgIcon->setPixmap(icon.pixmap(64, 64)); + + progress.buttonBox->button(QDialogButtonBox::Cancel)->setText("Abort"); + d.exec(); + }); + // Set up exit action QObject::connect(ui->actionExit, &QAction::triggered, this, &MainWindow::close); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index f429a8f..5f4fb98 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -720,6 +720,8 @@ File + + @@ -769,6 +771,16 @@ Check github.com for Updates + + + Turnstile Migration + + + + + Progress + + diff --git a/src/turnstile.ui b/src/turnstile.ui new file mode 100644 index 0000000..a12af05 --- /dev/null +++ b/src/turnstile.ui @@ -0,0 +1,229 @@ + + + Turnstile + + + + 0 + 0 + 565 + 416 + + + + Turnstile Migration + + + + + + Turnstile Migration + + + + + + + + + + + Qt::AlignCenter + + + + + + + Total Fees + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + Privacy Level + + + + + + + + 0 + 0 + + + + Miner Fee: + + + + + + + + 0 + 0 + + + + From + + + + + + + + 0 + 0 + + + + Dev Fee: + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 0.0004 ZEC $0.04 + + + + + + + 0.0004 ZEC $0.04 + + + + + + + + 0 + 0 + + + + false + + + + + + + + + + + 0 + 0 + + + + + + + + <html><head/><body><p>Funds from Sprout z-Addresses (which start with &quot;zc&quot;) need to be moved to the upgraded Sapling z-Addresses (which start with &quot;zs&quot;). The funds cannot be moved directly, but need to be sent through intermediate &quot;transparent&quot; addresses in privacy-preserving way.</p><p>This migration can be done automatically for you.</p></body></html> + + + true + + + + + + + + 0 + 0 + + + + To + + + + + + + + + + Qt::Horizontal + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + Turnstile + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Turnstile + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/turnstileprogress.ui b/src/turnstileprogress.ui new file mode 100644 index 0000000..5b09ebd --- /dev/null +++ b/src/turnstileprogress.ui @@ -0,0 +1,154 @@ + + + TurnstileProgress + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + + 33 + + + + + + + + 0 + 0 + + + + Please Ensure you have your wallet.dat backed up! + + + true + + + + + + + Qt::Horizontal + + + + + + + Next Transaction in 4 hours + + + + + + + 4 / 12 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Migration Progress + + + + + + + + 0 + 0 + + + + TextLabel + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + + + + + + buttonBox + accepted() + TurnstileProgress + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + TurnstileProgress + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/ui_mainwindow.h b/src/ui_mainwindow.h index a0f8192..3c9f656 100644 --- a/src/ui_mainwindow.h +++ b/src/ui_mainwindow.h @@ -47,6 +47,8 @@ public: QAction *actionDonate; QAction *actionImport_Private_Keys; QAction *actionCheck_for_Updates; + QAction *actionTurnstile_Migration; + QAction *actionProgress; QWidget *centralWidget; QGridLayout *gridLayout_3; QTabWidget *tabWidget; @@ -159,6 +161,10 @@ public: actionImport_Private_Keys->setVisible(false); actionCheck_for_Updates = new QAction(MainWindow); actionCheck_for_Updates->setObjectName(QStringLiteral("actionCheck_for_Updates")); + actionTurnstile_Migration = new QAction(MainWindow); + actionTurnstile_Migration->setObjectName(QStringLiteral("actionTurnstile_Migration")); + actionProgress = new QAction(MainWindow); + actionProgress->setObjectName(QStringLiteral("actionProgress")); centralWidget = new QWidget(MainWindow); centralWidget->setObjectName(QStringLiteral("centralWidget")); gridLayout_3 = new QGridLayout(centralWidget); @@ -666,6 +672,8 @@ public: menuBar->addAction(menuBalance->menuAction()); menuBar->addAction(menuHelp->menuAction()); menuBalance->addAction(actionImport_Private_Keys); + menuBalance->addAction(actionTurnstile_Migration); + menuBalance->addAction(actionProgress); menuBalance->addAction(actionSettings); menuBalance->addSeparator(); menuBalance->addAction(actionExit); @@ -690,6 +698,8 @@ public: actionDonate->setText(QApplication::translate("MainWindow", "Donate", nullptr)); actionImport_Private_Keys->setText(QApplication::translate("MainWindow", "Import Private Keys", nullptr)); actionCheck_for_Updates->setText(QApplication::translate("MainWindow", "Check github.com for Updates", nullptr)); + actionTurnstile_Migration->setText(QApplication::translate("MainWindow", "Turnstile Migration", nullptr)); + actionProgress->setText(QApplication::translate("MainWindow", "Progress", nullptr)); groupBox->setTitle(QApplication::translate("MainWindow", "Summary", nullptr)); label->setText(QApplication::translate("MainWindow", "Shielded", nullptr)); balSheilded->setText(QString()); diff --git a/src/ui_turnstile.h b/src/ui_turnstile.h new file mode 100644 index 0000000..8eb3566 --- /dev/null +++ b/src/ui_turnstile.h @@ -0,0 +1,210 @@ +/******************************************************************************** +** Form generated from reading UI file 'turnstile.ui' +** +** Created by: Qt User Interface Compiler version 5.11.2 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_TURNSTILE_H +#define UI_TURNSTILE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_Turnstile +{ +public: + QVBoxLayout *verticalLayout; + QGroupBox *groupBox; + QVBoxLayout *verticalLayout_2; + QGridLayout *gridLayout; + QLabel *msgIcon; + QLabel *label_3; + QLabel *label_2; + QLabel *label_4; + QLabel *label; + QLabel *label_5; + QSpacerItem *verticalSpacer; + QLabel *label_6; + QLabel *label_7; + QComboBox *migrateZaddList; + QComboBox *privLevel; + QLabel *label_8; + QLabel *label_9; + QComboBox *migrateTo; + QFrame *line; + QDialogButtonBox *buttonBox; + + void setupUi(QDialog *Turnstile) + { + if (Turnstile->objectName().isEmpty()) + Turnstile->setObjectName(QStringLiteral("Turnstile")); + Turnstile->resize(565, 416); + verticalLayout = new QVBoxLayout(Turnstile); + verticalLayout->setObjectName(QStringLiteral("verticalLayout")); + groupBox = new QGroupBox(Turnstile); + groupBox->setObjectName(QStringLiteral("groupBox")); + verticalLayout_2 = new QVBoxLayout(groupBox); + verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2")); + gridLayout = new QGridLayout(); + gridLayout->setObjectName(QStringLiteral("gridLayout")); + msgIcon = new QLabel(groupBox); + msgIcon->setObjectName(QStringLiteral("msgIcon")); + msgIcon->setAlignment(Qt::AlignCenter); + + gridLayout->addWidget(msgIcon, 0, 0, 1, 1); + + label_3 = new QLabel(groupBox); + label_3->setObjectName(QStringLiteral("label_3")); + label_3->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop); + + gridLayout->addWidget(label_3, 5, 0, 2, 1); + + label_2 = new QLabel(groupBox); + label_2->setObjectName(QStringLiteral("label_2")); + + gridLayout->addWidget(label_2, 4, 0, 1, 1); + + label_4 = new QLabel(groupBox); + label_4->setObjectName(QStringLiteral("label_4")); + QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(label_4->sizePolicy().hasHeightForWidth()); + label_4->setSizePolicy(sizePolicy); + + gridLayout->addWidget(label_4, 5, 1, 1, 1); + + label = new QLabel(groupBox); + label->setObjectName(QStringLiteral("label")); + QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Preferred); + sizePolicy1.setHorizontalStretch(0); + sizePolicy1.setVerticalStretch(0); + sizePolicy1.setHeightForWidth(label->sizePolicy().hasHeightForWidth()); + label->setSizePolicy(sizePolicy1); + + gridLayout->addWidget(label, 2, 0, 1, 1); + + label_5 = new QLabel(groupBox); + label_5->setObjectName(QStringLiteral("label_5")); + sizePolicy.setHeightForWidth(label_5->sizePolicy().hasHeightForWidth()); + label_5->setSizePolicy(sizePolicy); + + gridLayout->addWidget(label_5, 6, 1, 1, 1); + + verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + gridLayout->addItem(verticalSpacer, 7, 0, 1, 2); + + label_6 = new QLabel(groupBox); + label_6->setObjectName(QStringLiteral("label_6")); + + gridLayout->addWidget(label_6, 5, 2, 1, 1); + + label_7 = new QLabel(groupBox); + label_7->setObjectName(QStringLiteral("label_7")); + + gridLayout->addWidget(label_7, 6, 2, 1, 1); + + migrateZaddList = new QComboBox(groupBox); + migrateZaddList->setObjectName(QStringLiteral("migrateZaddList")); + QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Fixed); + sizePolicy2.setHorizontalStretch(0); + sizePolicy2.setVerticalStretch(0); + sizePolicy2.setHeightForWidth(migrateZaddList->sizePolicy().hasHeightForWidth()); + migrateZaddList->setSizePolicy(sizePolicy2); + migrateZaddList->setEditable(false); + + gridLayout->addWidget(migrateZaddList, 2, 1, 1, 2); + + privLevel = new QComboBox(groupBox); + privLevel->setObjectName(QStringLiteral("privLevel")); + sizePolicy2.setHeightForWidth(privLevel->sizePolicy().hasHeightForWidth()); + privLevel->setSizePolicy(sizePolicy2); + + gridLayout->addWidget(privLevel, 4, 1, 1, 2); + + label_8 = new QLabel(groupBox); + label_8->setObjectName(QStringLiteral("label_8")); + label_8->setWordWrap(true); + + gridLayout->addWidget(label_8, 0, 1, 1, 2); + + label_9 = new QLabel(groupBox); + label_9->setObjectName(QStringLiteral("label_9")); + sizePolicy1.setHeightForWidth(label_9->sizePolicy().hasHeightForWidth()); + label_9->setSizePolicy(sizePolicy1); + + gridLayout->addWidget(label_9, 3, 0, 1, 1); + + migrateTo = new QComboBox(groupBox); + migrateTo->setObjectName(QStringLiteral("migrateTo")); + + gridLayout->addWidget(migrateTo, 3, 1, 1, 2); + + line = new QFrame(groupBox); + line->setObjectName(QStringLiteral("line")); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + + gridLayout->addWidget(line, 1, 0, 1, 3); + + + verticalLayout_2->addLayout(gridLayout); + + + verticalLayout->addWidget(groupBox); + + buttonBox = new QDialogButtonBox(Turnstile); + buttonBox->setObjectName(QStringLiteral("buttonBox")); + buttonBox->setOrientation(Qt::Horizontal); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + + verticalLayout->addWidget(buttonBox); + + + retranslateUi(Turnstile); + QObject::connect(buttonBox, SIGNAL(accepted()), Turnstile, SLOT(accept())); + QObject::connect(buttonBox, SIGNAL(rejected()), Turnstile, SLOT(reject())); + + QMetaObject::connectSlotsByName(Turnstile); + } // setupUi + + void retranslateUi(QDialog *Turnstile) + { + Turnstile->setWindowTitle(QApplication::translate("Turnstile", "Turnstile Migration", nullptr)); + groupBox->setTitle(QApplication::translate("Turnstile", "Turnstile Migration", nullptr)); + msgIcon->setText(QString()); + label_3->setText(QApplication::translate("Turnstile", "Total Fees", nullptr)); + label_2->setText(QApplication::translate("Turnstile", "Privacy Level", nullptr)); + label_4->setText(QApplication::translate("Turnstile", "Miner Fee:", nullptr)); + label->setText(QApplication::translate("Turnstile", "From", nullptr)); + label_5->setText(QApplication::translate("Turnstile", "Dev Fee: ", nullptr)); + label_6->setText(QApplication::translate("Turnstile", "0.0004 ZEC $0.04", nullptr)); + label_7->setText(QApplication::translate("Turnstile", "0.0004 ZEC $0.04", nullptr)); + migrateZaddList->setCurrentText(QString()); + label_8->setText(QApplication::translate("Turnstile", "

Funds from Sprout z-Addresses (which start with "zc") need to be moved to the upgraded Sapling z-Addresses (which start with "zs"). The funds cannot be moved directly, but need to be sent through intermediate "transparent" addresses in privacy-preserving way.

This migration can be done automatically for you.

", nullptr)); + label_9->setText(QApplication::translate("Turnstile", "To", nullptr)); + } // retranslateUi + +}; + +namespace Ui { + class Turnstile: public Ui_Turnstile {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_TURNSTILE_H diff --git a/src/ui_turnstileprogress.h b/src/ui_turnstileprogress.h new file mode 100644 index 0000000..2d34909 --- /dev/null +++ b/src/ui_turnstileprogress.h @@ -0,0 +1,141 @@ +/******************************************************************************** +** Form generated from reading UI file 'turnstileprogress.ui' +** +** Created by: Qt User Interface Compiler version 5.11.2 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_TURNSTILEPROGRESS_H +#define UI_TURNSTILEPROGRESS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_TurnstileProgress +{ +public: + QGridLayout *gridLayout; + QProgressBar *progressBar; + QLabel *label_4; + QFrame *line; + QLabel *label; + QLabel *label_3; + QLabel *label_2; + QLabel *msgIcon; + QDialogButtonBox *buttonBox; + QSpacerItem *verticalSpacer; + QFrame *line_2; + + void setupUi(QDialog *TurnstileProgress) + { + if (TurnstileProgress->objectName().isEmpty()) + TurnstileProgress->setObjectName(QStringLiteral("TurnstileProgress")); + TurnstileProgress->resize(400, 300); + gridLayout = new QGridLayout(TurnstileProgress); + gridLayout->setObjectName(QStringLiteral("gridLayout")); + progressBar = new QProgressBar(TurnstileProgress); + progressBar->setObjectName(QStringLiteral("progressBar")); + progressBar->setValue(33); + + gridLayout->addWidget(progressBar, 3, 0, 1, 3); + + label_4 = new QLabel(TurnstileProgress); + label_4->setObjectName(QStringLiteral("label_4")); + QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(label_4->sizePolicy().hasHeightForWidth()); + label_4->setSizePolicy(sizePolicy); + label_4->setWordWrap(true); + + gridLayout->addWidget(label_4, 7, 1, 1, 2); + + line = new QFrame(TurnstileProgress); + line->setObjectName(QStringLiteral("line")); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + + gridLayout->addWidget(line, 4, 0, 1, 3); + + label = new QLabel(TurnstileProgress); + label->setObjectName(QStringLiteral("label")); + + gridLayout->addWidget(label, 5, 0, 1, 3); + + label_3 = new QLabel(TurnstileProgress); + label_3->setObjectName(QStringLiteral("label_3")); + label_3->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout->addWidget(label_3, 2, 2, 1, 1); + + label_2 = new QLabel(TurnstileProgress); + label_2->setObjectName(QStringLiteral("label_2")); + + gridLayout->addWidget(label_2, 2, 0, 1, 2); + + msgIcon = new QLabel(TurnstileProgress); + msgIcon->setObjectName(QStringLiteral("msgIcon")); + QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Preferred); + sizePolicy1.setHorizontalStretch(0); + sizePolicy1.setVerticalStretch(0); + sizePolicy1.setHeightForWidth(msgIcon->sizePolicy().hasHeightForWidth()); + msgIcon->setSizePolicy(sizePolicy1); + msgIcon->setAlignment(Qt::AlignCenter); + + gridLayout->addWidget(msgIcon, 7, 0, 1, 1); + + buttonBox = new QDialogButtonBox(TurnstileProgress); + buttonBox->setObjectName(QStringLiteral("buttonBox")); + buttonBox->setOrientation(Qt::Horizontal); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + + gridLayout->addWidget(buttonBox, 9, 0, 1, 3); + + verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + gridLayout->addItem(verticalSpacer, 6, 0, 1, 3); + + line_2 = new QFrame(TurnstileProgress); + line_2->setObjectName(QStringLiteral("line_2")); + line_2->setFrameShape(QFrame::HLine); + line_2->setFrameShadow(QFrame::Sunken); + + gridLayout->addWidget(line_2, 8, 0, 1, 3); + + + retranslateUi(TurnstileProgress); + QObject::connect(buttonBox, SIGNAL(accepted()), TurnstileProgress, SLOT(accept())); + QObject::connect(buttonBox, SIGNAL(rejected()), TurnstileProgress, SLOT(reject())); + + QMetaObject::connectSlotsByName(TurnstileProgress); + } // setupUi + + void retranslateUi(QDialog *TurnstileProgress) + { + TurnstileProgress->setWindowTitle(QApplication::translate("TurnstileProgress", "Dialog", nullptr)); + label_4->setText(QApplication::translate("TurnstileProgress", "Please Ensure you have your wallet.dat backed up!", nullptr)); + label->setText(QApplication::translate("TurnstileProgress", "Next Transaction in 4 hours", nullptr)); + label_3->setText(QApplication::translate("TurnstileProgress", "4 / 12", nullptr)); + label_2->setText(QApplication::translate("TurnstileProgress", "Migration Progress", nullptr)); + msgIcon->setText(QApplication::translate("TurnstileProgress", "TextLabel", nullptr)); + } // retranslateUi + +}; + +namespace Ui { + class TurnstileProgress: public Ui_TurnstileProgress {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_TURNSTILEPROGRESS_H diff --git a/zcash-qt-wallet.pro b/zcash-qt-wallet.pro index 5130567..7420b5c 100644 --- a/zcash-qt-wallet.pro +++ b/zcash-qt-wallet.pro @@ -71,7 +71,9 @@ FORMS += \ src/mainwindow.ui \ src/settings.ui \ src/about.ui \ - src/confirm.ui + src/confirm.ui \ + src/turnstile.ui \ + src/turnstileprogress.ui # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin From 90cf9d68965f3f534c26622e478493688c14706a Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Mon, 22 Oct 2018 22:10:52 -0700 Subject: [PATCH 02/25] Turnstile prototype --- src/mainwindow.cpp | 35 ++++++ src/mainwindow.ui | 12 ++ src/turnstile.ui | 229 +++++++++++++++++++++++++++++++++++++ src/turnstileprogress.ui | 154 +++++++++++++++++++++++++ src/ui_mainwindow.h | 10 ++ src/ui_turnstile.h | 210 ++++++++++++++++++++++++++++++++++ src/ui_turnstileprogress.h | 141 +++++++++++++++++++++++ zcash-qt-wallet.pro | 4 +- 8 files changed, 794 insertions(+), 1 deletion(-) create mode 100644 src/turnstile.ui create mode 100644 src/turnstileprogress.ui create mode 100644 src/ui_turnstile.h create mode 100644 src/ui_turnstileprogress.h diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 1c7c6d4..fe33645 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2,12 +2,15 @@ #include "ui_mainwindow.h" #include "ui_about.h" #include "ui_settings.h" +#include "ui_turnstile.h" +#include "ui_turnstileprogress.h" #include "rpc.h" #include "balancestablemodel.h" #include "settings.h" #include "utils.h" #include "senttxstore.h" + #include "precompiled.h" using json = nlohmann::json; @@ -24,6 +27,38 @@ MainWindow::MainWindow(QWidget *parent) : // Settings editor setupSettingsModal(); + // Turnstile migration + QObject::connect(ui->actionTurnstile_Migration, &QAction::triggered, [=] () { + Ui_Turnstile turnstile; + QDialog d(this); + turnstile.setupUi(&d); + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); + turnstile.msgIcon->setPixmap(icon.pixmap(64, 64)); + + turnstile.migrateZaddList->addItem("All Sprout z-Addrs"); + turnstile.migrateTo->addItem("zs1gv64eu0v2wx7raxqxlmj354y9ycznwaau9kduljzczxztvs4qcl00kn2sjxtejvrxnkucw5xx9u"); + turnstile.privLevel->addItem("Good - 3 tx over 3 days"); + turnstile.privLevel->addItem("Excellent - 5 tx over 5 days"); + turnstile.privLevel->addItem("Paranoid - 10 tx over 7 days"); + + turnstile.buttonBox->button(QDialogButtonBox::Ok)->setText("Start"); + + d.exec(); + }); + + QObject::connect(ui->actionProgress, &QAction::triggered, [=] () { + Ui_TurnstileProgress progress; + QDialog d(this); + progress.setupUi(&d); + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning); + progress.msgIcon->setPixmap(icon.pixmap(64, 64)); + + progress.buttonBox->button(QDialogButtonBox::Cancel)->setText("Abort"); + d.exec(); + }); + // Set up exit action QObject::connect(ui->actionExit, &QAction::triggered, this, &MainWindow::close); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index f429a8f..5f4fb98 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -720,6 +720,8 @@ File + + @@ -769,6 +771,16 @@ Check github.com for Updates + + + Turnstile Migration + + + + + Progress + + diff --git a/src/turnstile.ui b/src/turnstile.ui new file mode 100644 index 0000000..a12af05 --- /dev/null +++ b/src/turnstile.ui @@ -0,0 +1,229 @@ + + + Turnstile + + + + 0 + 0 + 565 + 416 + + + + Turnstile Migration + + + + + + Turnstile Migration + + + + + + + + + + + Qt::AlignCenter + + + + + + + Total Fees + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + Privacy Level + + + + + + + + 0 + 0 + + + + Miner Fee: + + + + + + + + 0 + 0 + + + + From + + + + + + + + 0 + 0 + + + + Dev Fee: + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 0.0004 ZEC $0.04 + + + + + + + 0.0004 ZEC $0.04 + + + + + + + + 0 + 0 + + + + false + + + + + + + + + + + 0 + 0 + + + + + + + + <html><head/><body><p>Funds from Sprout z-Addresses (which start with &quot;zc&quot;) need to be moved to the upgraded Sapling z-Addresses (which start with &quot;zs&quot;). The funds cannot be moved directly, but need to be sent through intermediate &quot;transparent&quot; addresses in privacy-preserving way.</p><p>This migration can be done automatically for you.</p></body></html> + + + true + + + + + + + + 0 + 0 + + + + To + + + + + + + + + + Qt::Horizontal + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + Turnstile + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Turnstile + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/turnstileprogress.ui b/src/turnstileprogress.ui new file mode 100644 index 0000000..5b09ebd --- /dev/null +++ b/src/turnstileprogress.ui @@ -0,0 +1,154 @@ + + + TurnstileProgress + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + + 33 + + + + + + + + 0 + 0 + + + + Please Ensure you have your wallet.dat backed up! + + + true + + + + + + + Qt::Horizontal + + + + + + + Next Transaction in 4 hours + + + + + + + 4 / 12 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Migration Progress + + + + + + + + 0 + 0 + + + + TextLabel + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + + + + + + buttonBox + accepted() + TurnstileProgress + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + TurnstileProgress + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/ui_mainwindow.h b/src/ui_mainwindow.h index a0f8192..3c9f656 100644 --- a/src/ui_mainwindow.h +++ b/src/ui_mainwindow.h @@ -47,6 +47,8 @@ public: QAction *actionDonate; QAction *actionImport_Private_Keys; QAction *actionCheck_for_Updates; + QAction *actionTurnstile_Migration; + QAction *actionProgress; QWidget *centralWidget; QGridLayout *gridLayout_3; QTabWidget *tabWidget; @@ -159,6 +161,10 @@ public: actionImport_Private_Keys->setVisible(false); actionCheck_for_Updates = new QAction(MainWindow); actionCheck_for_Updates->setObjectName(QStringLiteral("actionCheck_for_Updates")); + actionTurnstile_Migration = new QAction(MainWindow); + actionTurnstile_Migration->setObjectName(QStringLiteral("actionTurnstile_Migration")); + actionProgress = new QAction(MainWindow); + actionProgress->setObjectName(QStringLiteral("actionProgress")); centralWidget = new QWidget(MainWindow); centralWidget->setObjectName(QStringLiteral("centralWidget")); gridLayout_3 = new QGridLayout(centralWidget); @@ -666,6 +672,8 @@ public: menuBar->addAction(menuBalance->menuAction()); menuBar->addAction(menuHelp->menuAction()); menuBalance->addAction(actionImport_Private_Keys); + menuBalance->addAction(actionTurnstile_Migration); + menuBalance->addAction(actionProgress); menuBalance->addAction(actionSettings); menuBalance->addSeparator(); menuBalance->addAction(actionExit); @@ -690,6 +698,8 @@ public: actionDonate->setText(QApplication::translate("MainWindow", "Donate", nullptr)); actionImport_Private_Keys->setText(QApplication::translate("MainWindow", "Import Private Keys", nullptr)); actionCheck_for_Updates->setText(QApplication::translate("MainWindow", "Check github.com for Updates", nullptr)); + actionTurnstile_Migration->setText(QApplication::translate("MainWindow", "Turnstile Migration", nullptr)); + actionProgress->setText(QApplication::translate("MainWindow", "Progress", nullptr)); groupBox->setTitle(QApplication::translate("MainWindow", "Summary", nullptr)); label->setText(QApplication::translate("MainWindow", "Shielded", nullptr)); balSheilded->setText(QString()); diff --git a/src/ui_turnstile.h b/src/ui_turnstile.h new file mode 100644 index 0000000..8eb3566 --- /dev/null +++ b/src/ui_turnstile.h @@ -0,0 +1,210 @@ +/******************************************************************************** +** Form generated from reading UI file 'turnstile.ui' +** +** Created by: Qt User Interface Compiler version 5.11.2 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_TURNSTILE_H +#define UI_TURNSTILE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_Turnstile +{ +public: + QVBoxLayout *verticalLayout; + QGroupBox *groupBox; + QVBoxLayout *verticalLayout_2; + QGridLayout *gridLayout; + QLabel *msgIcon; + QLabel *label_3; + QLabel *label_2; + QLabel *label_4; + QLabel *label; + QLabel *label_5; + QSpacerItem *verticalSpacer; + QLabel *label_6; + QLabel *label_7; + QComboBox *migrateZaddList; + QComboBox *privLevel; + QLabel *label_8; + QLabel *label_9; + QComboBox *migrateTo; + QFrame *line; + QDialogButtonBox *buttonBox; + + void setupUi(QDialog *Turnstile) + { + if (Turnstile->objectName().isEmpty()) + Turnstile->setObjectName(QStringLiteral("Turnstile")); + Turnstile->resize(565, 416); + verticalLayout = new QVBoxLayout(Turnstile); + verticalLayout->setObjectName(QStringLiteral("verticalLayout")); + groupBox = new QGroupBox(Turnstile); + groupBox->setObjectName(QStringLiteral("groupBox")); + verticalLayout_2 = new QVBoxLayout(groupBox); + verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2")); + gridLayout = new QGridLayout(); + gridLayout->setObjectName(QStringLiteral("gridLayout")); + msgIcon = new QLabel(groupBox); + msgIcon->setObjectName(QStringLiteral("msgIcon")); + msgIcon->setAlignment(Qt::AlignCenter); + + gridLayout->addWidget(msgIcon, 0, 0, 1, 1); + + label_3 = new QLabel(groupBox); + label_3->setObjectName(QStringLiteral("label_3")); + label_3->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop); + + gridLayout->addWidget(label_3, 5, 0, 2, 1); + + label_2 = new QLabel(groupBox); + label_2->setObjectName(QStringLiteral("label_2")); + + gridLayout->addWidget(label_2, 4, 0, 1, 1); + + label_4 = new QLabel(groupBox); + label_4->setObjectName(QStringLiteral("label_4")); + QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(label_4->sizePolicy().hasHeightForWidth()); + label_4->setSizePolicy(sizePolicy); + + gridLayout->addWidget(label_4, 5, 1, 1, 1); + + label = new QLabel(groupBox); + label->setObjectName(QStringLiteral("label")); + QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Preferred); + sizePolicy1.setHorizontalStretch(0); + sizePolicy1.setVerticalStretch(0); + sizePolicy1.setHeightForWidth(label->sizePolicy().hasHeightForWidth()); + label->setSizePolicy(sizePolicy1); + + gridLayout->addWidget(label, 2, 0, 1, 1); + + label_5 = new QLabel(groupBox); + label_5->setObjectName(QStringLiteral("label_5")); + sizePolicy.setHeightForWidth(label_5->sizePolicy().hasHeightForWidth()); + label_5->setSizePolicy(sizePolicy); + + gridLayout->addWidget(label_5, 6, 1, 1, 1); + + verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + gridLayout->addItem(verticalSpacer, 7, 0, 1, 2); + + label_6 = new QLabel(groupBox); + label_6->setObjectName(QStringLiteral("label_6")); + + gridLayout->addWidget(label_6, 5, 2, 1, 1); + + label_7 = new QLabel(groupBox); + label_7->setObjectName(QStringLiteral("label_7")); + + gridLayout->addWidget(label_7, 6, 2, 1, 1); + + migrateZaddList = new QComboBox(groupBox); + migrateZaddList->setObjectName(QStringLiteral("migrateZaddList")); + QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Fixed); + sizePolicy2.setHorizontalStretch(0); + sizePolicy2.setVerticalStretch(0); + sizePolicy2.setHeightForWidth(migrateZaddList->sizePolicy().hasHeightForWidth()); + migrateZaddList->setSizePolicy(sizePolicy2); + migrateZaddList->setEditable(false); + + gridLayout->addWidget(migrateZaddList, 2, 1, 1, 2); + + privLevel = new QComboBox(groupBox); + privLevel->setObjectName(QStringLiteral("privLevel")); + sizePolicy2.setHeightForWidth(privLevel->sizePolicy().hasHeightForWidth()); + privLevel->setSizePolicy(sizePolicy2); + + gridLayout->addWidget(privLevel, 4, 1, 1, 2); + + label_8 = new QLabel(groupBox); + label_8->setObjectName(QStringLiteral("label_8")); + label_8->setWordWrap(true); + + gridLayout->addWidget(label_8, 0, 1, 1, 2); + + label_9 = new QLabel(groupBox); + label_9->setObjectName(QStringLiteral("label_9")); + sizePolicy1.setHeightForWidth(label_9->sizePolicy().hasHeightForWidth()); + label_9->setSizePolicy(sizePolicy1); + + gridLayout->addWidget(label_9, 3, 0, 1, 1); + + migrateTo = new QComboBox(groupBox); + migrateTo->setObjectName(QStringLiteral("migrateTo")); + + gridLayout->addWidget(migrateTo, 3, 1, 1, 2); + + line = new QFrame(groupBox); + line->setObjectName(QStringLiteral("line")); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + + gridLayout->addWidget(line, 1, 0, 1, 3); + + + verticalLayout_2->addLayout(gridLayout); + + + verticalLayout->addWidget(groupBox); + + buttonBox = new QDialogButtonBox(Turnstile); + buttonBox->setObjectName(QStringLiteral("buttonBox")); + buttonBox->setOrientation(Qt::Horizontal); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + + verticalLayout->addWidget(buttonBox); + + + retranslateUi(Turnstile); + QObject::connect(buttonBox, SIGNAL(accepted()), Turnstile, SLOT(accept())); + QObject::connect(buttonBox, SIGNAL(rejected()), Turnstile, SLOT(reject())); + + QMetaObject::connectSlotsByName(Turnstile); + } // setupUi + + void retranslateUi(QDialog *Turnstile) + { + Turnstile->setWindowTitle(QApplication::translate("Turnstile", "Turnstile Migration", nullptr)); + groupBox->setTitle(QApplication::translate("Turnstile", "Turnstile Migration", nullptr)); + msgIcon->setText(QString()); + label_3->setText(QApplication::translate("Turnstile", "Total Fees", nullptr)); + label_2->setText(QApplication::translate("Turnstile", "Privacy Level", nullptr)); + label_4->setText(QApplication::translate("Turnstile", "Miner Fee:", nullptr)); + label->setText(QApplication::translate("Turnstile", "From", nullptr)); + label_5->setText(QApplication::translate("Turnstile", "Dev Fee: ", nullptr)); + label_6->setText(QApplication::translate("Turnstile", "0.0004 ZEC $0.04", nullptr)); + label_7->setText(QApplication::translate("Turnstile", "0.0004 ZEC $0.04", nullptr)); + migrateZaddList->setCurrentText(QString()); + label_8->setText(QApplication::translate("Turnstile", "

Funds from Sprout z-Addresses (which start with "zc") need to be moved to the upgraded Sapling z-Addresses (which start with "zs"). The funds cannot be moved directly, but need to be sent through intermediate "transparent" addresses in privacy-preserving way.

This migration can be done automatically for you.

", nullptr)); + label_9->setText(QApplication::translate("Turnstile", "To", nullptr)); + } // retranslateUi + +}; + +namespace Ui { + class Turnstile: public Ui_Turnstile {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_TURNSTILE_H diff --git a/src/ui_turnstileprogress.h b/src/ui_turnstileprogress.h new file mode 100644 index 0000000..2d34909 --- /dev/null +++ b/src/ui_turnstileprogress.h @@ -0,0 +1,141 @@ +/******************************************************************************** +** Form generated from reading UI file 'turnstileprogress.ui' +** +** Created by: Qt User Interface Compiler version 5.11.2 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_TURNSTILEPROGRESS_H +#define UI_TURNSTILEPROGRESS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_TurnstileProgress +{ +public: + QGridLayout *gridLayout; + QProgressBar *progressBar; + QLabel *label_4; + QFrame *line; + QLabel *label; + QLabel *label_3; + QLabel *label_2; + QLabel *msgIcon; + QDialogButtonBox *buttonBox; + QSpacerItem *verticalSpacer; + QFrame *line_2; + + void setupUi(QDialog *TurnstileProgress) + { + if (TurnstileProgress->objectName().isEmpty()) + TurnstileProgress->setObjectName(QStringLiteral("TurnstileProgress")); + TurnstileProgress->resize(400, 300); + gridLayout = new QGridLayout(TurnstileProgress); + gridLayout->setObjectName(QStringLiteral("gridLayout")); + progressBar = new QProgressBar(TurnstileProgress); + progressBar->setObjectName(QStringLiteral("progressBar")); + progressBar->setValue(33); + + gridLayout->addWidget(progressBar, 3, 0, 1, 3); + + label_4 = new QLabel(TurnstileProgress); + label_4->setObjectName(QStringLiteral("label_4")); + QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(label_4->sizePolicy().hasHeightForWidth()); + label_4->setSizePolicy(sizePolicy); + label_4->setWordWrap(true); + + gridLayout->addWidget(label_4, 7, 1, 1, 2); + + line = new QFrame(TurnstileProgress); + line->setObjectName(QStringLiteral("line")); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + + gridLayout->addWidget(line, 4, 0, 1, 3); + + label = new QLabel(TurnstileProgress); + label->setObjectName(QStringLiteral("label")); + + gridLayout->addWidget(label, 5, 0, 1, 3); + + label_3 = new QLabel(TurnstileProgress); + label_3->setObjectName(QStringLiteral("label_3")); + label_3->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout->addWidget(label_3, 2, 2, 1, 1); + + label_2 = new QLabel(TurnstileProgress); + label_2->setObjectName(QStringLiteral("label_2")); + + gridLayout->addWidget(label_2, 2, 0, 1, 2); + + msgIcon = new QLabel(TurnstileProgress); + msgIcon->setObjectName(QStringLiteral("msgIcon")); + QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Preferred); + sizePolicy1.setHorizontalStretch(0); + sizePolicy1.setVerticalStretch(0); + sizePolicy1.setHeightForWidth(msgIcon->sizePolicy().hasHeightForWidth()); + msgIcon->setSizePolicy(sizePolicy1); + msgIcon->setAlignment(Qt::AlignCenter); + + gridLayout->addWidget(msgIcon, 7, 0, 1, 1); + + buttonBox = new QDialogButtonBox(TurnstileProgress); + buttonBox->setObjectName(QStringLiteral("buttonBox")); + buttonBox->setOrientation(Qt::Horizontal); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + + gridLayout->addWidget(buttonBox, 9, 0, 1, 3); + + verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + gridLayout->addItem(verticalSpacer, 6, 0, 1, 3); + + line_2 = new QFrame(TurnstileProgress); + line_2->setObjectName(QStringLiteral("line_2")); + line_2->setFrameShape(QFrame::HLine); + line_2->setFrameShadow(QFrame::Sunken); + + gridLayout->addWidget(line_2, 8, 0, 1, 3); + + + retranslateUi(TurnstileProgress); + QObject::connect(buttonBox, SIGNAL(accepted()), TurnstileProgress, SLOT(accept())); + QObject::connect(buttonBox, SIGNAL(rejected()), TurnstileProgress, SLOT(reject())); + + QMetaObject::connectSlotsByName(TurnstileProgress); + } // setupUi + + void retranslateUi(QDialog *TurnstileProgress) + { + TurnstileProgress->setWindowTitle(QApplication::translate("TurnstileProgress", "Dialog", nullptr)); + label_4->setText(QApplication::translate("TurnstileProgress", "Please Ensure you have your wallet.dat backed up!", nullptr)); + label->setText(QApplication::translate("TurnstileProgress", "Next Transaction in 4 hours", nullptr)); + label_3->setText(QApplication::translate("TurnstileProgress", "4 / 12", nullptr)); + label_2->setText(QApplication::translate("TurnstileProgress", "Migration Progress", nullptr)); + msgIcon->setText(QApplication::translate("TurnstileProgress", "TextLabel", nullptr)); + } // retranslateUi + +}; + +namespace Ui { + class TurnstileProgress: public Ui_TurnstileProgress {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_TURNSTILEPROGRESS_H diff --git a/zcash-qt-wallet.pro b/zcash-qt-wallet.pro index 2a9bf3b..6abb239 100644 --- a/zcash-qt-wallet.pro +++ b/zcash-qt-wallet.pro @@ -71,7 +71,9 @@ FORMS += \ src/mainwindow.ui \ src/settings.ui \ src/about.ui \ - src/confirm.ui + src/confirm.ui \ + src/turnstile.ui \ + src/turnstileprogress.ui # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin From 4929dd417ca31aaa607edf0cc4c31dbc80b34c9b Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Mon, 22 Oct 2018 22:10:52 -0700 Subject: [PATCH 03/25] Turnstile prototype --- src/mainwindow.cpp | 35 ++++++ src/mainwindow.ui | 12 ++ src/turnstile.ui | 229 +++++++++++++++++++++++++++++++++++++ src/turnstileprogress.ui | 154 +++++++++++++++++++++++++ src/ui_mainwindow.h | 10 ++ src/ui_turnstile.h | 210 ++++++++++++++++++++++++++++++++++ src/ui_turnstileprogress.h | 141 +++++++++++++++++++++++ zec-qt-wallet.pro | 4 +- 8 files changed, 794 insertions(+), 1 deletion(-) create mode 100644 src/turnstile.ui create mode 100644 src/turnstileprogress.ui create mode 100644 src/ui_turnstile.h create mode 100644 src/ui_turnstileprogress.h diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2606f6d..d03c0a6 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2,12 +2,15 @@ #include "ui_mainwindow.h" #include "ui_about.h" #include "ui_settings.h" +#include "ui_turnstile.h" +#include "ui_turnstileprogress.h" #include "rpc.h" #include "balancestablemodel.h" #include "settings.h" #include "utils.h" #include "senttxstore.h" + #include "precompiled.h" using json = nlohmann::json; @@ -24,6 +27,38 @@ MainWindow::MainWindow(QWidget *parent) : // Settings editor setupSettingsModal(); + // Turnstile migration + QObject::connect(ui->actionTurnstile_Migration, &QAction::triggered, [=] () { + Ui_Turnstile turnstile; + QDialog d(this); + turnstile.setupUi(&d); + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); + turnstile.msgIcon->setPixmap(icon.pixmap(64, 64)); + + turnstile.migrateZaddList->addItem("All Sprout z-Addrs"); + turnstile.migrateTo->addItem("zs1gv64eu0v2wx7raxqxlmj354y9ycznwaau9kduljzczxztvs4qcl00kn2sjxtejvrxnkucw5xx9u"); + turnstile.privLevel->addItem("Good - 3 tx over 3 days"); + turnstile.privLevel->addItem("Excellent - 5 tx over 5 days"); + turnstile.privLevel->addItem("Paranoid - 10 tx over 7 days"); + + turnstile.buttonBox->button(QDialogButtonBox::Ok)->setText("Start"); + + d.exec(); + }); + + QObject::connect(ui->actionProgress, &QAction::triggered, [=] () { + Ui_TurnstileProgress progress; + QDialog d(this); + progress.setupUi(&d); + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning); + progress.msgIcon->setPixmap(icon.pixmap(64, 64)); + + progress.buttonBox->button(QDialogButtonBox::Cancel)->setText("Abort"); + d.exec(); + }); + // Set up exit action QObject::connect(ui->actionExit, &QAction::triggered, this, &MainWindow::close); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 4baf922..9e408c4 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -720,6 +720,8 @@ File + + @@ -769,6 +771,16 @@ Check github.com for Updates + + + Turnstile Migration + + + + + Progress + + diff --git a/src/turnstile.ui b/src/turnstile.ui new file mode 100644 index 0000000..a12af05 --- /dev/null +++ b/src/turnstile.ui @@ -0,0 +1,229 @@ + + + Turnstile + + + + 0 + 0 + 565 + 416 + + + + Turnstile Migration + + + + + + Turnstile Migration + + + + + + + + + + + Qt::AlignCenter + + + + + + + Total Fees + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + Privacy Level + + + + + + + + 0 + 0 + + + + Miner Fee: + + + + + + + + 0 + 0 + + + + From + + + + + + + + 0 + 0 + + + + Dev Fee: + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 0.0004 ZEC $0.04 + + + + + + + 0.0004 ZEC $0.04 + + + + + + + + 0 + 0 + + + + false + + + + + + + + + + + 0 + 0 + + + + + + + + <html><head/><body><p>Funds from Sprout z-Addresses (which start with &quot;zc&quot;) need to be moved to the upgraded Sapling z-Addresses (which start with &quot;zs&quot;). The funds cannot be moved directly, but need to be sent through intermediate &quot;transparent&quot; addresses in privacy-preserving way.</p><p>This migration can be done automatically for you.</p></body></html> + + + true + + + + + + + + 0 + 0 + + + + To + + + + + + + + + + Qt::Horizontal + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + Turnstile + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Turnstile + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/turnstileprogress.ui b/src/turnstileprogress.ui new file mode 100644 index 0000000..5b09ebd --- /dev/null +++ b/src/turnstileprogress.ui @@ -0,0 +1,154 @@ + + + TurnstileProgress + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + + 33 + + + + + + + + 0 + 0 + + + + Please Ensure you have your wallet.dat backed up! + + + true + + + + + + + Qt::Horizontal + + + + + + + Next Transaction in 4 hours + + + + + + + 4 / 12 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Migration Progress + + + + + + + + 0 + 0 + + + + TextLabel + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + + + + + + buttonBox + accepted() + TurnstileProgress + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + TurnstileProgress + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/ui_mainwindow.h b/src/ui_mainwindow.h index c9a29ea..ac1195a 100644 --- a/src/ui_mainwindow.h +++ b/src/ui_mainwindow.h @@ -47,6 +47,8 @@ public: QAction *actionDonate; QAction *actionImport_Private_Keys; QAction *actionCheck_for_Updates; + QAction *actionTurnstile_Migration; + QAction *actionProgress; QWidget *centralWidget; QGridLayout *gridLayout_3; QTabWidget *tabWidget; @@ -159,6 +161,10 @@ public: actionImport_Private_Keys->setVisible(false); actionCheck_for_Updates = new QAction(MainWindow); actionCheck_for_Updates->setObjectName(QStringLiteral("actionCheck_for_Updates")); + actionTurnstile_Migration = new QAction(MainWindow); + actionTurnstile_Migration->setObjectName(QStringLiteral("actionTurnstile_Migration")); + actionProgress = new QAction(MainWindow); + actionProgress->setObjectName(QStringLiteral("actionProgress")); centralWidget = new QWidget(MainWindow); centralWidget->setObjectName(QStringLiteral("centralWidget")); gridLayout_3 = new QGridLayout(centralWidget); @@ -666,6 +672,8 @@ public: menuBar->addAction(menuBalance->menuAction()); menuBar->addAction(menuHelp->menuAction()); menuBalance->addAction(actionImport_Private_Keys); + menuBalance->addAction(actionTurnstile_Migration); + menuBalance->addAction(actionProgress); menuBalance->addAction(actionSettings); menuBalance->addSeparator(); menuBalance->addAction(actionExit); @@ -690,6 +698,8 @@ public: actionDonate->setText(QApplication::translate("MainWindow", "Donate", nullptr)); actionImport_Private_Keys->setText(QApplication::translate("MainWindow", "Import Private Keys", nullptr)); actionCheck_for_Updates->setText(QApplication::translate("MainWindow", "Check github.com for Updates", nullptr)); + actionTurnstile_Migration->setText(QApplication::translate("MainWindow", "Turnstile Migration", nullptr)); + actionProgress->setText(QApplication::translate("MainWindow", "Progress", nullptr)); groupBox->setTitle(QApplication::translate("MainWindow", "Summary", nullptr)); label->setText(QApplication::translate("MainWindow", "Shielded", nullptr)); balSheilded->setText(QString()); diff --git a/src/ui_turnstile.h b/src/ui_turnstile.h new file mode 100644 index 0000000..8eb3566 --- /dev/null +++ b/src/ui_turnstile.h @@ -0,0 +1,210 @@ +/******************************************************************************** +** Form generated from reading UI file 'turnstile.ui' +** +** Created by: Qt User Interface Compiler version 5.11.2 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_TURNSTILE_H +#define UI_TURNSTILE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_Turnstile +{ +public: + QVBoxLayout *verticalLayout; + QGroupBox *groupBox; + QVBoxLayout *verticalLayout_2; + QGridLayout *gridLayout; + QLabel *msgIcon; + QLabel *label_3; + QLabel *label_2; + QLabel *label_4; + QLabel *label; + QLabel *label_5; + QSpacerItem *verticalSpacer; + QLabel *label_6; + QLabel *label_7; + QComboBox *migrateZaddList; + QComboBox *privLevel; + QLabel *label_8; + QLabel *label_9; + QComboBox *migrateTo; + QFrame *line; + QDialogButtonBox *buttonBox; + + void setupUi(QDialog *Turnstile) + { + if (Turnstile->objectName().isEmpty()) + Turnstile->setObjectName(QStringLiteral("Turnstile")); + Turnstile->resize(565, 416); + verticalLayout = new QVBoxLayout(Turnstile); + verticalLayout->setObjectName(QStringLiteral("verticalLayout")); + groupBox = new QGroupBox(Turnstile); + groupBox->setObjectName(QStringLiteral("groupBox")); + verticalLayout_2 = new QVBoxLayout(groupBox); + verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2")); + gridLayout = new QGridLayout(); + gridLayout->setObjectName(QStringLiteral("gridLayout")); + msgIcon = new QLabel(groupBox); + msgIcon->setObjectName(QStringLiteral("msgIcon")); + msgIcon->setAlignment(Qt::AlignCenter); + + gridLayout->addWidget(msgIcon, 0, 0, 1, 1); + + label_3 = new QLabel(groupBox); + label_3->setObjectName(QStringLiteral("label_3")); + label_3->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop); + + gridLayout->addWidget(label_3, 5, 0, 2, 1); + + label_2 = new QLabel(groupBox); + label_2->setObjectName(QStringLiteral("label_2")); + + gridLayout->addWidget(label_2, 4, 0, 1, 1); + + label_4 = new QLabel(groupBox); + label_4->setObjectName(QStringLiteral("label_4")); + QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(label_4->sizePolicy().hasHeightForWidth()); + label_4->setSizePolicy(sizePolicy); + + gridLayout->addWidget(label_4, 5, 1, 1, 1); + + label = new QLabel(groupBox); + label->setObjectName(QStringLiteral("label")); + QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Preferred); + sizePolicy1.setHorizontalStretch(0); + sizePolicy1.setVerticalStretch(0); + sizePolicy1.setHeightForWidth(label->sizePolicy().hasHeightForWidth()); + label->setSizePolicy(sizePolicy1); + + gridLayout->addWidget(label, 2, 0, 1, 1); + + label_5 = new QLabel(groupBox); + label_5->setObjectName(QStringLiteral("label_5")); + sizePolicy.setHeightForWidth(label_5->sizePolicy().hasHeightForWidth()); + label_5->setSizePolicy(sizePolicy); + + gridLayout->addWidget(label_5, 6, 1, 1, 1); + + verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + gridLayout->addItem(verticalSpacer, 7, 0, 1, 2); + + label_6 = new QLabel(groupBox); + label_6->setObjectName(QStringLiteral("label_6")); + + gridLayout->addWidget(label_6, 5, 2, 1, 1); + + label_7 = new QLabel(groupBox); + label_7->setObjectName(QStringLiteral("label_7")); + + gridLayout->addWidget(label_7, 6, 2, 1, 1); + + migrateZaddList = new QComboBox(groupBox); + migrateZaddList->setObjectName(QStringLiteral("migrateZaddList")); + QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Fixed); + sizePolicy2.setHorizontalStretch(0); + sizePolicy2.setVerticalStretch(0); + sizePolicy2.setHeightForWidth(migrateZaddList->sizePolicy().hasHeightForWidth()); + migrateZaddList->setSizePolicy(sizePolicy2); + migrateZaddList->setEditable(false); + + gridLayout->addWidget(migrateZaddList, 2, 1, 1, 2); + + privLevel = new QComboBox(groupBox); + privLevel->setObjectName(QStringLiteral("privLevel")); + sizePolicy2.setHeightForWidth(privLevel->sizePolicy().hasHeightForWidth()); + privLevel->setSizePolicy(sizePolicy2); + + gridLayout->addWidget(privLevel, 4, 1, 1, 2); + + label_8 = new QLabel(groupBox); + label_8->setObjectName(QStringLiteral("label_8")); + label_8->setWordWrap(true); + + gridLayout->addWidget(label_8, 0, 1, 1, 2); + + label_9 = new QLabel(groupBox); + label_9->setObjectName(QStringLiteral("label_9")); + sizePolicy1.setHeightForWidth(label_9->sizePolicy().hasHeightForWidth()); + label_9->setSizePolicy(sizePolicy1); + + gridLayout->addWidget(label_9, 3, 0, 1, 1); + + migrateTo = new QComboBox(groupBox); + migrateTo->setObjectName(QStringLiteral("migrateTo")); + + gridLayout->addWidget(migrateTo, 3, 1, 1, 2); + + line = new QFrame(groupBox); + line->setObjectName(QStringLiteral("line")); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + + gridLayout->addWidget(line, 1, 0, 1, 3); + + + verticalLayout_2->addLayout(gridLayout); + + + verticalLayout->addWidget(groupBox); + + buttonBox = new QDialogButtonBox(Turnstile); + buttonBox->setObjectName(QStringLiteral("buttonBox")); + buttonBox->setOrientation(Qt::Horizontal); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + + verticalLayout->addWidget(buttonBox); + + + retranslateUi(Turnstile); + QObject::connect(buttonBox, SIGNAL(accepted()), Turnstile, SLOT(accept())); + QObject::connect(buttonBox, SIGNAL(rejected()), Turnstile, SLOT(reject())); + + QMetaObject::connectSlotsByName(Turnstile); + } // setupUi + + void retranslateUi(QDialog *Turnstile) + { + Turnstile->setWindowTitle(QApplication::translate("Turnstile", "Turnstile Migration", nullptr)); + groupBox->setTitle(QApplication::translate("Turnstile", "Turnstile Migration", nullptr)); + msgIcon->setText(QString()); + label_3->setText(QApplication::translate("Turnstile", "Total Fees", nullptr)); + label_2->setText(QApplication::translate("Turnstile", "Privacy Level", nullptr)); + label_4->setText(QApplication::translate("Turnstile", "Miner Fee:", nullptr)); + label->setText(QApplication::translate("Turnstile", "From", nullptr)); + label_5->setText(QApplication::translate("Turnstile", "Dev Fee: ", nullptr)); + label_6->setText(QApplication::translate("Turnstile", "0.0004 ZEC $0.04", nullptr)); + label_7->setText(QApplication::translate("Turnstile", "0.0004 ZEC $0.04", nullptr)); + migrateZaddList->setCurrentText(QString()); + label_8->setText(QApplication::translate("Turnstile", "

Funds from Sprout z-Addresses (which start with "zc") need to be moved to the upgraded Sapling z-Addresses (which start with "zs"). The funds cannot be moved directly, but need to be sent through intermediate "transparent" addresses in privacy-preserving way.

This migration can be done automatically for you.

", nullptr)); + label_9->setText(QApplication::translate("Turnstile", "To", nullptr)); + } // retranslateUi + +}; + +namespace Ui { + class Turnstile: public Ui_Turnstile {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_TURNSTILE_H diff --git a/src/ui_turnstileprogress.h b/src/ui_turnstileprogress.h new file mode 100644 index 0000000..2d34909 --- /dev/null +++ b/src/ui_turnstileprogress.h @@ -0,0 +1,141 @@ +/******************************************************************************** +** Form generated from reading UI file 'turnstileprogress.ui' +** +** Created by: Qt User Interface Compiler version 5.11.2 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_TURNSTILEPROGRESS_H +#define UI_TURNSTILEPROGRESS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_TurnstileProgress +{ +public: + QGridLayout *gridLayout; + QProgressBar *progressBar; + QLabel *label_4; + QFrame *line; + QLabel *label; + QLabel *label_3; + QLabel *label_2; + QLabel *msgIcon; + QDialogButtonBox *buttonBox; + QSpacerItem *verticalSpacer; + QFrame *line_2; + + void setupUi(QDialog *TurnstileProgress) + { + if (TurnstileProgress->objectName().isEmpty()) + TurnstileProgress->setObjectName(QStringLiteral("TurnstileProgress")); + TurnstileProgress->resize(400, 300); + gridLayout = new QGridLayout(TurnstileProgress); + gridLayout->setObjectName(QStringLiteral("gridLayout")); + progressBar = new QProgressBar(TurnstileProgress); + progressBar->setObjectName(QStringLiteral("progressBar")); + progressBar->setValue(33); + + gridLayout->addWidget(progressBar, 3, 0, 1, 3); + + label_4 = new QLabel(TurnstileProgress); + label_4->setObjectName(QStringLiteral("label_4")); + QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(label_4->sizePolicy().hasHeightForWidth()); + label_4->setSizePolicy(sizePolicy); + label_4->setWordWrap(true); + + gridLayout->addWidget(label_4, 7, 1, 1, 2); + + line = new QFrame(TurnstileProgress); + line->setObjectName(QStringLiteral("line")); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + + gridLayout->addWidget(line, 4, 0, 1, 3); + + label = new QLabel(TurnstileProgress); + label->setObjectName(QStringLiteral("label")); + + gridLayout->addWidget(label, 5, 0, 1, 3); + + label_3 = new QLabel(TurnstileProgress); + label_3->setObjectName(QStringLiteral("label_3")); + label_3->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout->addWidget(label_3, 2, 2, 1, 1); + + label_2 = new QLabel(TurnstileProgress); + label_2->setObjectName(QStringLiteral("label_2")); + + gridLayout->addWidget(label_2, 2, 0, 1, 2); + + msgIcon = new QLabel(TurnstileProgress); + msgIcon->setObjectName(QStringLiteral("msgIcon")); + QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Preferred); + sizePolicy1.setHorizontalStretch(0); + sizePolicy1.setVerticalStretch(0); + sizePolicy1.setHeightForWidth(msgIcon->sizePolicy().hasHeightForWidth()); + msgIcon->setSizePolicy(sizePolicy1); + msgIcon->setAlignment(Qt::AlignCenter); + + gridLayout->addWidget(msgIcon, 7, 0, 1, 1); + + buttonBox = new QDialogButtonBox(TurnstileProgress); + buttonBox->setObjectName(QStringLiteral("buttonBox")); + buttonBox->setOrientation(Qt::Horizontal); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + + gridLayout->addWidget(buttonBox, 9, 0, 1, 3); + + verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + gridLayout->addItem(verticalSpacer, 6, 0, 1, 3); + + line_2 = new QFrame(TurnstileProgress); + line_2->setObjectName(QStringLiteral("line_2")); + line_2->setFrameShape(QFrame::HLine); + line_2->setFrameShadow(QFrame::Sunken); + + gridLayout->addWidget(line_2, 8, 0, 1, 3); + + + retranslateUi(TurnstileProgress); + QObject::connect(buttonBox, SIGNAL(accepted()), TurnstileProgress, SLOT(accept())); + QObject::connect(buttonBox, SIGNAL(rejected()), TurnstileProgress, SLOT(reject())); + + QMetaObject::connectSlotsByName(TurnstileProgress); + } // setupUi + + void retranslateUi(QDialog *TurnstileProgress) + { + TurnstileProgress->setWindowTitle(QApplication::translate("TurnstileProgress", "Dialog", nullptr)); + label_4->setText(QApplication::translate("TurnstileProgress", "Please Ensure you have your wallet.dat backed up!", nullptr)); + label->setText(QApplication::translate("TurnstileProgress", "Next Transaction in 4 hours", nullptr)); + label_3->setText(QApplication::translate("TurnstileProgress", "4 / 12", nullptr)); + label_2->setText(QApplication::translate("TurnstileProgress", "Migration Progress", nullptr)); + msgIcon->setText(QApplication::translate("TurnstileProgress", "TextLabel", nullptr)); + } // retranslateUi + +}; + +namespace Ui { + class TurnstileProgress: public Ui_TurnstileProgress {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_TURNSTILEPROGRESS_H diff --git a/zec-qt-wallet.pro b/zec-qt-wallet.pro index 5c913e3..497a23c 100644 --- a/zec-qt-wallet.pro +++ b/zec-qt-wallet.pro @@ -71,7 +71,9 @@ FORMS += \ src/mainwindow.ui \ src/settings.ui \ src/about.ui \ - src/confirm.ui + src/confirm.ui \ + src/turnstile.ui \ + src/turnstileprogress.ui # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin From be26b2a8e3fe49ebce9323af17b9be4815392196 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Mon, 22 Oct 2018 22:10:52 -0700 Subject: [PATCH 04/25] Turnstile prototype --- src/mainwindow.cpp | 35 ++++++ src/mainwindow.ui | 12 ++ src/turnstile.ui | 229 +++++++++++++++++++++++++++++++++++++ src/turnstileprogress.ui | 154 +++++++++++++++++++++++++ src/ui_mainwindow.h | 10 ++ src/ui_turnstile.h | 210 ++++++++++++++++++++++++++++++++++ src/ui_turnstileprogress.h | 141 +++++++++++++++++++++++ zec-qt-wallet.pro | 4 +- 8 files changed, 794 insertions(+), 1 deletion(-) create mode 100644 src/turnstile.ui create mode 100644 src/turnstileprogress.ui create mode 100644 src/ui_turnstile.h create mode 100644 src/ui_turnstileprogress.h diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2606f6d..d03c0a6 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2,12 +2,15 @@ #include "ui_mainwindow.h" #include "ui_about.h" #include "ui_settings.h" +#include "ui_turnstile.h" +#include "ui_turnstileprogress.h" #include "rpc.h" #include "balancestablemodel.h" #include "settings.h" #include "utils.h" #include "senttxstore.h" + #include "precompiled.h" using json = nlohmann::json; @@ -24,6 +27,38 @@ MainWindow::MainWindow(QWidget *parent) : // Settings editor setupSettingsModal(); + // Turnstile migration + QObject::connect(ui->actionTurnstile_Migration, &QAction::triggered, [=] () { + Ui_Turnstile turnstile; + QDialog d(this); + turnstile.setupUi(&d); + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); + turnstile.msgIcon->setPixmap(icon.pixmap(64, 64)); + + turnstile.migrateZaddList->addItem("All Sprout z-Addrs"); + turnstile.migrateTo->addItem("zs1gv64eu0v2wx7raxqxlmj354y9ycznwaau9kduljzczxztvs4qcl00kn2sjxtejvrxnkucw5xx9u"); + turnstile.privLevel->addItem("Good - 3 tx over 3 days"); + turnstile.privLevel->addItem("Excellent - 5 tx over 5 days"); + turnstile.privLevel->addItem("Paranoid - 10 tx over 7 days"); + + turnstile.buttonBox->button(QDialogButtonBox::Ok)->setText("Start"); + + d.exec(); + }); + + QObject::connect(ui->actionProgress, &QAction::triggered, [=] () { + Ui_TurnstileProgress progress; + QDialog d(this); + progress.setupUi(&d); + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning); + progress.msgIcon->setPixmap(icon.pixmap(64, 64)); + + progress.buttonBox->button(QDialogButtonBox::Cancel)->setText("Abort"); + d.exec(); + }); + // Set up exit action QObject::connect(ui->actionExit, &QAction::triggered, this, &MainWindow::close); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 4baf922..9e408c4 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -720,6 +720,8 @@ File + + @@ -769,6 +771,16 @@ Check github.com for Updates + + + Turnstile Migration + + + + + Progress + + diff --git a/src/turnstile.ui b/src/turnstile.ui new file mode 100644 index 0000000..a12af05 --- /dev/null +++ b/src/turnstile.ui @@ -0,0 +1,229 @@ + + + Turnstile + + + + 0 + 0 + 565 + 416 + + + + Turnstile Migration + + + + + + Turnstile Migration + + + + + + + + + + + Qt::AlignCenter + + + + + + + Total Fees + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + Privacy Level + + + + + + + + 0 + 0 + + + + Miner Fee: + + + + + + + + 0 + 0 + + + + From + + + + + + + + 0 + 0 + + + + Dev Fee: + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 0.0004 ZEC $0.04 + + + + + + + 0.0004 ZEC $0.04 + + + + + + + + 0 + 0 + + + + false + + + + + + + + + + + 0 + 0 + + + + + + + + <html><head/><body><p>Funds from Sprout z-Addresses (which start with &quot;zc&quot;) need to be moved to the upgraded Sapling z-Addresses (which start with &quot;zs&quot;). The funds cannot be moved directly, but need to be sent through intermediate &quot;transparent&quot; addresses in privacy-preserving way.</p><p>This migration can be done automatically for you.</p></body></html> + + + true + + + + + + + + 0 + 0 + + + + To + + + + + + + + + + Qt::Horizontal + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + Turnstile + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Turnstile + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/turnstileprogress.ui b/src/turnstileprogress.ui new file mode 100644 index 0000000..5b09ebd --- /dev/null +++ b/src/turnstileprogress.ui @@ -0,0 +1,154 @@ + + + TurnstileProgress + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + + 33 + + + + + + + + 0 + 0 + + + + Please Ensure you have your wallet.dat backed up! + + + true + + + + + + + Qt::Horizontal + + + + + + + Next Transaction in 4 hours + + + + + + + 4 / 12 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Migration Progress + + + + + + + + 0 + 0 + + + + TextLabel + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + + + + + + buttonBox + accepted() + TurnstileProgress + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + TurnstileProgress + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/ui_mainwindow.h b/src/ui_mainwindow.h index c9a29ea..ac1195a 100644 --- a/src/ui_mainwindow.h +++ b/src/ui_mainwindow.h @@ -47,6 +47,8 @@ public: QAction *actionDonate; QAction *actionImport_Private_Keys; QAction *actionCheck_for_Updates; + QAction *actionTurnstile_Migration; + QAction *actionProgress; QWidget *centralWidget; QGridLayout *gridLayout_3; QTabWidget *tabWidget; @@ -159,6 +161,10 @@ public: actionImport_Private_Keys->setVisible(false); actionCheck_for_Updates = new QAction(MainWindow); actionCheck_for_Updates->setObjectName(QStringLiteral("actionCheck_for_Updates")); + actionTurnstile_Migration = new QAction(MainWindow); + actionTurnstile_Migration->setObjectName(QStringLiteral("actionTurnstile_Migration")); + actionProgress = new QAction(MainWindow); + actionProgress->setObjectName(QStringLiteral("actionProgress")); centralWidget = new QWidget(MainWindow); centralWidget->setObjectName(QStringLiteral("centralWidget")); gridLayout_3 = new QGridLayout(centralWidget); @@ -666,6 +672,8 @@ public: menuBar->addAction(menuBalance->menuAction()); menuBar->addAction(menuHelp->menuAction()); menuBalance->addAction(actionImport_Private_Keys); + menuBalance->addAction(actionTurnstile_Migration); + menuBalance->addAction(actionProgress); menuBalance->addAction(actionSettings); menuBalance->addSeparator(); menuBalance->addAction(actionExit); @@ -690,6 +698,8 @@ public: actionDonate->setText(QApplication::translate("MainWindow", "Donate", nullptr)); actionImport_Private_Keys->setText(QApplication::translate("MainWindow", "Import Private Keys", nullptr)); actionCheck_for_Updates->setText(QApplication::translate("MainWindow", "Check github.com for Updates", nullptr)); + actionTurnstile_Migration->setText(QApplication::translate("MainWindow", "Turnstile Migration", nullptr)); + actionProgress->setText(QApplication::translate("MainWindow", "Progress", nullptr)); groupBox->setTitle(QApplication::translate("MainWindow", "Summary", nullptr)); label->setText(QApplication::translate("MainWindow", "Shielded", nullptr)); balSheilded->setText(QString()); diff --git a/src/ui_turnstile.h b/src/ui_turnstile.h new file mode 100644 index 0000000..8eb3566 --- /dev/null +++ b/src/ui_turnstile.h @@ -0,0 +1,210 @@ +/******************************************************************************** +** Form generated from reading UI file 'turnstile.ui' +** +** Created by: Qt User Interface Compiler version 5.11.2 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_TURNSTILE_H +#define UI_TURNSTILE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_Turnstile +{ +public: + QVBoxLayout *verticalLayout; + QGroupBox *groupBox; + QVBoxLayout *verticalLayout_2; + QGridLayout *gridLayout; + QLabel *msgIcon; + QLabel *label_3; + QLabel *label_2; + QLabel *label_4; + QLabel *label; + QLabel *label_5; + QSpacerItem *verticalSpacer; + QLabel *label_6; + QLabel *label_7; + QComboBox *migrateZaddList; + QComboBox *privLevel; + QLabel *label_8; + QLabel *label_9; + QComboBox *migrateTo; + QFrame *line; + QDialogButtonBox *buttonBox; + + void setupUi(QDialog *Turnstile) + { + if (Turnstile->objectName().isEmpty()) + Turnstile->setObjectName(QStringLiteral("Turnstile")); + Turnstile->resize(565, 416); + verticalLayout = new QVBoxLayout(Turnstile); + verticalLayout->setObjectName(QStringLiteral("verticalLayout")); + groupBox = new QGroupBox(Turnstile); + groupBox->setObjectName(QStringLiteral("groupBox")); + verticalLayout_2 = new QVBoxLayout(groupBox); + verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2")); + gridLayout = new QGridLayout(); + gridLayout->setObjectName(QStringLiteral("gridLayout")); + msgIcon = new QLabel(groupBox); + msgIcon->setObjectName(QStringLiteral("msgIcon")); + msgIcon->setAlignment(Qt::AlignCenter); + + gridLayout->addWidget(msgIcon, 0, 0, 1, 1); + + label_3 = new QLabel(groupBox); + label_3->setObjectName(QStringLiteral("label_3")); + label_3->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop); + + gridLayout->addWidget(label_3, 5, 0, 2, 1); + + label_2 = new QLabel(groupBox); + label_2->setObjectName(QStringLiteral("label_2")); + + gridLayout->addWidget(label_2, 4, 0, 1, 1); + + label_4 = new QLabel(groupBox); + label_4->setObjectName(QStringLiteral("label_4")); + QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(label_4->sizePolicy().hasHeightForWidth()); + label_4->setSizePolicy(sizePolicy); + + gridLayout->addWidget(label_4, 5, 1, 1, 1); + + label = new QLabel(groupBox); + label->setObjectName(QStringLiteral("label")); + QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Preferred); + sizePolicy1.setHorizontalStretch(0); + sizePolicy1.setVerticalStretch(0); + sizePolicy1.setHeightForWidth(label->sizePolicy().hasHeightForWidth()); + label->setSizePolicy(sizePolicy1); + + gridLayout->addWidget(label, 2, 0, 1, 1); + + label_5 = new QLabel(groupBox); + label_5->setObjectName(QStringLiteral("label_5")); + sizePolicy.setHeightForWidth(label_5->sizePolicy().hasHeightForWidth()); + label_5->setSizePolicy(sizePolicy); + + gridLayout->addWidget(label_5, 6, 1, 1, 1); + + verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + gridLayout->addItem(verticalSpacer, 7, 0, 1, 2); + + label_6 = new QLabel(groupBox); + label_6->setObjectName(QStringLiteral("label_6")); + + gridLayout->addWidget(label_6, 5, 2, 1, 1); + + label_7 = new QLabel(groupBox); + label_7->setObjectName(QStringLiteral("label_7")); + + gridLayout->addWidget(label_7, 6, 2, 1, 1); + + migrateZaddList = new QComboBox(groupBox); + migrateZaddList->setObjectName(QStringLiteral("migrateZaddList")); + QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Fixed); + sizePolicy2.setHorizontalStretch(0); + sizePolicy2.setVerticalStretch(0); + sizePolicy2.setHeightForWidth(migrateZaddList->sizePolicy().hasHeightForWidth()); + migrateZaddList->setSizePolicy(sizePolicy2); + migrateZaddList->setEditable(false); + + gridLayout->addWidget(migrateZaddList, 2, 1, 1, 2); + + privLevel = new QComboBox(groupBox); + privLevel->setObjectName(QStringLiteral("privLevel")); + sizePolicy2.setHeightForWidth(privLevel->sizePolicy().hasHeightForWidth()); + privLevel->setSizePolicy(sizePolicy2); + + gridLayout->addWidget(privLevel, 4, 1, 1, 2); + + label_8 = new QLabel(groupBox); + label_8->setObjectName(QStringLiteral("label_8")); + label_8->setWordWrap(true); + + gridLayout->addWidget(label_8, 0, 1, 1, 2); + + label_9 = new QLabel(groupBox); + label_9->setObjectName(QStringLiteral("label_9")); + sizePolicy1.setHeightForWidth(label_9->sizePolicy().hasHeightForWidth()); + label_9->setSizePolicy(sizePolicy1); + + gridLayout->addWidget(label_9, 3, 0, 1, 1); + + migrateTo = new QComboBox(groupBox); + migrateTo->setObjectName(QStringLiteral("migrateTo")); + + gridLayout->addWidget(migrateTo, 3, 1, 1, 2); + + line = new QFrame(groupBox); + line->setObjectName(QStringLiteral("line")); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + + gridLayout->addWidget(line, 1, 0, 1, 3); + + + verticalLayout_2->addLayout(gridLayout); + + + verticalLayout->addWidget(groupBox); + + buttonBox = new QDialogButtonBox(Turnstile); + buttonBox->setObjectName(QStringLiteral("buttonBox")); + buttonBox->setOrientation(Qt::Horizontal); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + + verticalLayout->addWidget(buttonBox); + + + retranslateUi(Turnstile); + QObject::connect(buttonBox, SIGNAL(accepted()), Turnstile, SLOT(accept())); + QObject::connect(buttonBox, SIGNAL(rejected()), Turnstile, SLOT(reject())); + + QMetaObject::connectSlotsByName(Turnstile); + } // setupUi + + void retranslateUi(QDialog *Turnstile) + { + Turnstile->setWindowTitle(QApplication::translate("Turnstile", "Turnstile Migration", nullptr)); + groupBox->setTitle(QApplication::translate("Turnstile", "Turnstile Migration", nullptr)); + msgIcon->setText(QString()); + label_3->setText(QApplication::translate("Turnstile", "Total Fees", nullptr)); + label_2->setText(QApplication::translate("Turnstile", "Privacy Level", nullptr)); + label_4->setText(QApplication::translate("Turnstile", "Miner Fee:", nullptr)); + label->setText(QApplication::translate("Turnstile", "From", nullptr)); + label_5->setText(QApplication::translate("Turnstile", "Dev Fee: ", nullptr)); + label_6->setText(QApplication::translate("Turnstile", "0.0004 ZEC $0.04", nullptr)); + label_7->setText(QApplication::translate("Turnstile", "0.0004 ZEC $0.04", nullptr)); + migrateZaddList->setCurrentText(QString()); + label_8->setText(QApplication::translate("Turnstile", "

Funds from Sprout z-Addresses (which start with "zc") need to be moved to the upgraded Sapling z-Addresses (which start with "zs"). The funds cannot be moved directly, but need to be sent through intermediate "transparent" addresses in privacy-preserving way.

This migration can be done automatically for you.

", nullptr)); + label_9->setText(QApplication::translate("Turnstile", "To", nullptr)); + } // retranslateUi + +}; + +namespace Ui { + class Turnstile: public Ui_Turnstile {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_TURNSTILE_H diff --git a/src/ui_turnstileprogress.h b/src/ui_turnstileprogress.h new file mode 100644 index 0000000..2d34909 --- /dev/null +++ b/src/ui_turnstileprogress.h @@ -0,0 +1,141 @@ +/******************************************************************************** +** Form generated from reading UI file 'turnstileprogress.ui' +** +** Created by: Qt User Interface Compiler version 5.11.2 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_TURNSTILEPROGRESS_H +#define UI_TURNSTILEPROGRESS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_TurnstileProgress +{ +public: + QGridLayout *gridLayout; + QProgressBar *progressBar; + QLabel *label_4; + QFrame *line; + QLabel *label; + QLabel *label_3; + QLabel *label_2; + QLabel *msgIcon; + QDialogButtonBox *buttonBox; + QSpacerItem *verticalSpacer; + QFrame *line_2; + + void setupUi(QDialog *TurnstileProgress) + { + if (TurnstileProgress->objectName().isEmpty()) + TurnstileProgress->setObjectName(QStringLiteral("TurnstileProgress")); + TurnstileProgress->resize(400, 300); + gridLayout = new QGridLayout(TurnstileProgress); + gridLayout->setObjectName(QStringLiteral("gridLayout")); + progressBar = new QProgressBar(TurnstileProgress); + progressBar->setObjectName(QStringLiteral("progressBar")); + progressBar->setValue(33); + + gridLayout->addWidget(progressBar, 3, 0, 1, 3); + + label_4 = new QLabel(TurnstileProgress); + label_4->setObjectName(QStringLiteral("label_4")); + QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(label_4->sizePolicy().hasHeightForWidth()); + label_4->setSizePolicy(sizePolicy); + label_4->setWordWrap(true); + + gridLayout->addWidget(label_4, 7, 1, 1, 2); + + line = new QFrame(TurnstileProgress); + line->setObjectName(QStringLiteral("line")); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + + gridLayout->addWidget(line, 4, 0, 1, 3); + + label = new QLabel(TurnstileProgress); + label->setObjectName(QStringLiteral("label")); + + gridLayout->addWidget(label, 5, 0, 1, 3); + + label_3 = new QLabel(TurnstileProgress); + label_3->setObjectName(QStringLiteral("label_3")); + label_3->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout->addWidget(label_3, 2, 2, 1, 1); + + label_2 = new QLabel(TurnstileProgress); + label_2->setObjectName(QStringLiteral("label_2")); + + gridLayout->addWidget(label_2, 2, 0, 1, 2); + + msgIcon = new QLabel(TurnstileProgress); + msgIcon->setObjectName(QStringLiteral("msgIcon")); + QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Preferred); + sizePolicy1.setHorizontalStretch(0); + sizePolicy1.setVerticalStretch(0); + sizePolicy1.setHeightForWidth(msgIcon->sizePolicy().hasHeightForWidth()); + msgIcon->setSizePolicy(sizePolicy1); + msgIcon->setAlignment(Qt::AlignCenter); + + gridLayout->addWidget(msgIcon, 7, 0, 1, 1); + + buttonBox = new QDialogButtonBox(TurnstileProgress); + buttonBox->setObjectName(QStringLiteral("buttonBox")); + buttonBox->setOrientation(Qt::Horizontal); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + + gridLayout->addWidget(buttonBox, 9, 0, 1, 3); + + verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + gridLayout->addItem(verticalSpacer, 6, 0, 1, 3); + + line_2 = new QFrame(TurnstileProgress); + line_2->setObjectName(QStringLiteral("line_2")); + line_2->setFrameShape(QFrame::HLine); + line_2->setFrameShadow(QFrame::Sunken); + + gridLayout->addWidget(line_2, 8, 0, 1, 3); + + + retranslateUi(TurnstileProgress); + QObject::connect(buttonBox, SIGNAL(accepted()), TurnstileProgress, SLOT(accept())); + QObject::connect(buttonBox, SIGNAL(rejected()), TurnstileProgress, SLOT(reject())); + + QMetaObject::connectSlotsByName(TurnstileProgress); + } // setupUi + + void retranslateUi(QDialog *TurnstileProgress) + { + TurnstileProgress->setWindowTitle(QApplication::translate("TurnstileProgress", "Dialog", nullptr)); + label_4->setText(QApplication::translate("TurnstileProgress", "Please Ensure you have your wallet.dat backed up!", nullptr)); + label->setText(QApplication::translate("TurnstileProgress", "Next Transaction in 4 hours", nullptr)); + label_3->setText(QApplication::translate("TurnstileProgress", "4 / 12", nullptr)); + label_2->setText(QApplication::translate("TurnstileProgress", "Migration Progress", nullptr)); + msgIcon->setText(QApplication::translate("TurnstileProgress", "TextLabel", nullptr)); + } // retranslateUi + +}; + +namespace Ui { + class TurnstileProgress: public Ui_TurnstileProgress {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_TURNSTILEPROGRESS_H diff --git a/zec-qt-wallet.pro b/zec-qt-wallet.pro index 5c913e3..497a23c 100644 --- a/zec-qt-wallet.pro +++ b/zec-qt-wallet.pro @@ -71,7 +71,9 @@ FORMS += \ src/mainwindow.ui \ src/settings.ui \ src/about.ui \ - src/confirm.ui + src/confirm.ui \ + src/turnstile.ui \ + src/turnstileprogress.ui # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin From 444e16e97311e5fb025b7e3970922a4c8bd95749 Mon Sep 17 00:00:00 2001 From: adityapk00 Date: Wed, 24 Oct 2018 21:06:03 -0700 Subject: [PATCH 05/25] intermediate checkin --- src/main.cpp | 8 ++++++++ src/precompiled.h | 2 ++ src/turnstile.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/turnstile.h | 11 +++++++++++ zec-qt-wallet.pro | 2 ++ 5 files changed, 60 insertions(+) create mode 100644 src/turnstile.cpp create mode 100644 src/turnstile.h diff --git a/src/main.cpp b/src/main.cpp index 76b6873..f96df19 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,7 @@ #include "mainwindow.h" #include "settings.h" +#include "turnstile.h" + #include "precompiled.h" int main(int argc, char *argv[]) @@ -16,6 +18,8 @@ int main(int argc, char *argv[]) qApp->setFont(QFont("Ubuntu", 11, QFont::Normal, false)); #endif + std::srand(std::time(nullptr)); + QCoreApplication::setOrganizationName("zec-qt-wallet-org"); QCoreApplication::setApplicationName("zec-qt-wallet"); @@ -24,6 +28,10 @@ int main(int argc, char *argv[]) MainWindow w; w.setWindowTitle("zec-qt-wallet v" + QString(APP_VERSION)); w.show(); + + // Temp + Turnstile t; + qDebug() << t.splitAmount(1245.2294371, 3); return QApplication::exec(); } diff --git a/src/precompiled.h b/src/precompiled.h index c3e837b..976fba1 100644 --- a/src/precompiled.h +++ b/src/precompiled.h @@ -2,6 +2,8 @@ /* Add C++ includes here */ #include +#include +#include #include #include diff --git a/src/turnstile.cpp b/src/turnstile.cpp new file mode 100644 index 0000000..c442d70 --- /dev/null +++ b/src/turnstile.cpp @@ -0,0 +1,37 @@ +#include "precompiled.h" +#include "turnstile.h" + + +Turnstile::Turnstile() { +} + + +Turnstile::~Turnstile() { +} + +QList Turnstile::splitAmount(double amount, int parts) { + QList amounts; + fillAmounts(amounts, amount, parts); + + // Ensure they all add up! + double sumofparts = 0; + for (auto a : amounts) { + sumofparts += a.toDouble(); + } + + Q_ASSERT(sumofparts == amount); + return amounts; +} + +void Turnstile::fillAmounts(QList& amounts, double amount, int count) { + if (count == 1 || amount < 1) { + amounts.push_back(QString::number(amount, 'g', 8)); + return; + } + + // Get a random amount off the amount and call recursively. + auto curAmount = std::rand() % (int)std::floor(amount); + amounts.push_back(QString::number(curAmount, 'g', 8)); + + fillAmounts(amounts, amount - curAmount, count - 1); +} \ No newline at end of file diff --git a/src/turnstile.h b/src/turnstile.h new file mode 100644 index 0000000..0da7098 --- /dev/null +++ b/src/turnstile.h @@ -0,0 +1,11 @@ +#pragma once +class Turnstile +{ +public: + Turnstile(); + ~Turnstile(); + + QList Turnstile::splitAmount(double amount, int parts); + void fillAmounts(QList& amounts, double amount, int count); +}; + diff --git a/zec-qt-wallet.pro b/zec-qt-wallet.pro index 497a23c..7ae1f78 100644 --- a/zec-qt-wallet.pro +++ b/zec-qt-wallet.pro @@ -50,6 +50,7 @@ SOURCES += \ src/sendtab.cpp \ src/senttxstore.cpp \ src/txtablemodel.cpp \ + src/turnstile.cpp \ src/utils.cpp HEADERS += \ @@ -65,6 +66,7 @@ HEADERS += \ src/settings.h \ src/txtablemodel.h \ src/senttxstore.h \ + src/turnstile.h \ src/utils.h FORMS += \ From bdeefef95ae97e3fd958ec5ed62a5856a146f949 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Wed, 24 Oct 2018 22:28:55 -0700 Subject: [PATCH 06/25] Split up amounts --- src/main.cpp | 6 +++++- src/mainwindow.cpp | 1 - src/precompiled.h | 1 + src/turnstile.cpp | 40 ++++++++++++++++++++++++++++++++-------- src/turnstile.h | 11 ++++++++--- 5 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index f96df19..b73e119 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,7 +31,11 @@ int main(int argc, char *argv[]) // Temp Turnstile t; - qDebug() << t.splitAmount(1245.2294371, 3); + double amt = 2329127.99999999; + qDebug() << QString::number(amt, 'f', 8) << ":"; + for (auto a : t.splitAmount(amt, 3)) { + qDebug() << QString::number(a, 'f', 8); + } return QApplication::exec(); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d03c0a6..9816d6a 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -10,7 +10,6 @@ #include "utils.h" #include "senttxstore.h" - #include "precompiled.h" using json = nlohmann::json; diff --git a/src/precompiled.h b/src/precompiled.h index 976fba1..552226d 100644 --- a/src/precompiled.h +++ b/src/precompiled.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include diff --git a/src/turnstile.cpp b/src/turnstile.cpp index c442d70..bb15260 100644 --- a/src/turnstile.cpp +++ b/src/turnstile.cpp @@ -1,6 +1,6 @@ -#include "precompiled.h" #include "turnstile.h" +#include "utils.h" Turnstile::Turnstile() { } @@ -9,29 +9,53 @@ Turnstile::Turnstile() { Turnstile::~Turnstile() { } -QList Turnstile::splitAmount(double amount, int parts) { - QList amounts; +QList Turnstile::splitAmount(double amount, int parts) { + QList amounts; fillAmounts(amounts, amount, parts); // Ensure they all add up! double sumofparts = 0; for (auto a : amounts) { - sumofparts += a.toDouble(); + sumofparts += a; } Q_ASSERT(sumofparts == amount); return amounts; } -void Turnstile::fillAmounts(QList& amounts, double amount, int count) { +void Turnstile::fillAmounts(QList& amounts, double amount, int count) { if (count == 1 || amount < 1) { - amounts.push_back(QString::number(amount, 'g', 8)); + // Split the chaff. + // Chaff is all amounts lesser than 0.0001 ZEC. The chaff will be added to the + // dev fee, and is done so to protect privacy. + + // Get the rounded value to 4 decimal places (approx $0.01) + double actual = std::floor(amount * 10000) / 10000; + + // Reduce the Dev Tx fee from the amount + actual = actual - 0.0001; //Utils::getDevFee(); + + // Calculate the chaff. + double chaff = amount - actual; + + amounts.push_back(actual); + if (chaff > 0.00000001) // zcash is split down to 8 decimal places + amounts.push_back(chaff); return; } - // Get a random amount off the amount and call recursively. + // Get a random amount off the amount (between half and full) and call recursively. auto curAmount = std::rand() % (int)std::floor(amount); - amounts.push_back(QString::number(curAmount, 'g', 8)); + + // Try to round it off + if (curAmount > 1000) { + curAmount = std::floor(curAmount / 100) * 100; + } else if (curAmount > 100) { + curAmount = std::floor(curAmount / 10) * 10; + } + + if (curAmount > 0) + amounts.push_back(curAmount); fillAmounts(amounts, amount - curAmount, count - 1); } \ No newline at end of file diff --git a/src/turnstile.h b/src/turnstile.h index 0da7098..7a4bac7 100644 --- a/src/turnstile.h +++ b/src/turnstile.h @@ -1,11 +1,16 @@ -#pragma once +#ifndef TURNSTILE_H +#define TURNSTILE_H + +#include "precompiled.h" + class Turnstile { public: Turnstile(); ~Turnstile(); - QList Turnstile::splitAmount(double amount, int parts); - void fillAmounts(QList& amounts, double amount, int count); + QList splitAmount(double amount, int parts); + void fillAmounts(QList& amounts, double amount, int count); }; +#endif \ No newline at end of file From b9b99aea9392a05fdf5e28049bbce5fa0fcd981b Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Wed, 24 Oct 2018 22:33:45 -0700 Subject: [PATCH 07/25] Account for tx fees --- src/turnstile.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/turnstile.cpp b/src/turnstile.cpp index bb15260..349db59 100644 --- a/src/turnstile.cpp +++ b/src/turnstile.cpp @@ -35,6 +35,9 @@ void Turnstile::fillAmounts(QList& amounts, double amount, int count) { // Reduce the Dev Tx fee from the amount actual = actual - 0.0001; //Utils::getDevFee(); + // Also account for the fees needed to send all these transactions + actual = actual - (Utils::getMinerFee() * (amounts.size() + 1)); + // Calculate the chaff. double chaff = amount - actual; From ca9fcd754dd2d91f6cf241472db234d09d0bfe5b Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Wed, 24 Oct 2018 22:44:45 -0700 Subject: [PATCH 08/25] Add min --- src/turnstile.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/turnstile.cpp b/src/turnstile.cpp index 349db59..a4f8f94 100644 --- a/src/turnstile.cpp +++ b/src/turnstile.cpp @@ -11,6 +11,10 @@ Turnstile::~Turnstile() { QList Turnstile::splitAmount(double amount, int parts) { QList amounts; + // Need at least 0.0004 ZEC for this + if (amount < 0.0004) + return amounts; + fillAmounts(amounts, amount, parts); // Ensure they all add up! From e84a24c5496ad426bec31aa4ff5ac0139923c778 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Thu, 25 Oct 2018 09:44:40 -0700 Subject: [PATCH 09/25] minor --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index b73e119..96581a4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) // Temp Turnstile t; - double amt = 2329127.99999999; + double amt = 0.0003; qDebug() << QString::number(amt, 'f', 8) << ":"; for (auto a : t.splitAmount(amt, 3)) { qDebug() << QString::number(a, 'f', 8); From 66b09aa344178c45ff91ddb4b5c72772a33653db Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Thu, 25 Oct 2018 11:52:02 -0700 Subject: [PATCH 10/25] create migration plan --- README.md | 4 +- src/main.cpp | 8 ---- src/rpc.cpp | 61 ++++-------------------- src/rpc.h | 54 +++++++++++++++++++-- src/turnstile.cpp | 117 ++++++++++++++++++++++++++++++++++++++++++++-- src/turnstile.h | 23 ++++++++- zec-qt-wallet.pro | 2 +- 7 files changed, 198 insertions(+), 71 deletions(-) diff --git a/README.md b/README.md index b29c990..4f13a91 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,8 @@ Head over to the releases page and grab the latest binary. https://github.com/ad ### Linux Extract and run the binary ``` -tar -xvf zec-qt-wallet-v0.2.2.tar.gz -./zec-qt-wallet-v0.2.2/zec-qt-wallet +tar -xvf zec-qt-wallet-v0.2.3.tar.gz +./zec-qt-wallet-v0.2.3/zec-qt-wallet ``` ### Windows diff --git a/src/main.cpp b/src/main.cpp index 96581a4..c86c2af 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,14 +28,6 @@ int main(int argc, char *argv[]) MainWindow w; w.setWindowTitle("zec-qt-wallet v" + QString(APP_VERSION)); w.show(); - - // Temp - Turnstile t; - double amt = 0.0003; - qDebug() << QString::number(amt, 'f', 8) << ":"; - for (auto a : t.splitAmount(amt, 3)) { - qDebug() << QString::number(a, 'f', 8); - } return QApplication::exec(); } diff --git a/src/rpc.cpp b/src/rpc.cpp index 5dce998..c70a6f1 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -2,6 +2,7 @@ #include "utils.h" #include "settings.h" #include "senttxstore.h" +#include "turnstile.h" using json = nlohmann::json; @@ -46,6 +47,7 @@ RPC::RPC(QNetworkAccessManager* client, MainWindow* main) { }); // Start at every 10s. When an operation is pending, this will change to every second txTimer->start(Utils::updateSpeed); + } RPC::~RPC() { @@ -284,54 +286,6 @@ void RPC::handleTxError(const QString& error) { msg.exec(); } - -void RPC::getBatchRPC( - const QList& payloads, - std::function payloadGenerator, - std::function*)> cb) -{ - auto responses = new QMap(); // zAddr -> list of responses for each call. - int totalSize = payloads.size(); - - for (auto item: payloads) { - json payload = payloadGenerator(item); - - QNetworkReply *reply = restclient->post(request, QByteArray::fromStdString(payload.dump())); - - QObject::connect(reply, &QNetworkReply::finished, [=] { - reply->deleteLater(); - - auto all = reply->readAll(); - auto parsed = json::parse(all.toStdString(), nullptr, false); - - if (reply->error() != QNetworkReply::NoError) { - qDebug() << QString::fromStdString(parsed.dump()); - qDebug() << reply->errorString(); - - (*responses)[item] = json::object(); // Empty object - } else { - if (parsed.is_discarded()) { - (*responses)[item] = json::object(); // Empty object - } else { - (*responses)[item] = parsed["result"]; - } - } - }); - } - - auto waitTimer = new QTimer(main); - QObject::connect(waitTimer, &QTimer::timeout, [=]() { - if (responses->size() == totalSize) { - waitTimer->stop(); - - cb(responses); - - waitTimer->deleteLater(); - } - }); - waitTimer->start(100); -} - // Refresh received z txs by calling z_listreceivedbyaddress/gettransaction void RPC::refreshReceivedZTrans(QList zaddrs) { @@ -349,7 +303,7 @@ void RPC::refreshReceivedZTrans(QList zaddrs) { // and each z-Addr can have multiple received txs. // 1. For each z-Addr, get list of received txs - getBatchRPC(zaddrs, + getBatchRPC(zaddrs, [=] (QString zaddr) { json payload = { {"jsonrpc", "1.0"}, @@ -373,7 +327,7 @@ void RPC::refreshReceivedZTrans(QList zaddrs) { } // 2. For all txids, go and get the details of that txid. - getBatchRPC(txids.toList(), + getBatchRPC(txids.toList(), [=] (QString txid) { json payload = { {"jsonrpc", "1.0"}, @@ -507,6 +461,11 @@ void RPC::refreshAddresses() { // Function to create the data model and update the views, used below. void RPC::updateUI(bool anyUnconfirmed) { + + // Temp + Turnstile t(this); + t.planMigration(zaddresses->at(1), zaddresses->at(0)); + ui->unconfirmedWarning->setVisible(anyUnconfirmed); // Update balances model data, which will update the table too @@ -624,7 +583,7 @@ void RPC::refreshSentZTrans() { } // Look up all the txids to get the confirmation count for them. - getBatchRPC(txids, + getBatchRPC(txids, [=] (QString txid) { json payload = { {"jsonrpc", "1.0"}, diff --git a/src/rpc.h b/src/rpc.h index bdb903b..1bbd6fd 100644 --- a/src/rpc.h +++ b/src/rpc.h @@ -46,6 +46,55 @@ public: void newZaddr (bool sapling, const std::function& cb); void newTaddr (const std::function& cb); + // Batch method. Note: Because of the template, it has to be in the header file. + template + void getBatchRPC(const QList& payloads, + std::function payloadGenerator, + std::function*)> cb) { + auto responses = new QMap(); // zAddr -> list of responses for each call. + int totalSize = payloads.size(); + + for (auto item: payloads) { + json payload = payloadGenerator(item); + + QNetworkReply *reply = restclient->post(request, QByteArray::fromStdString(payload.dump())); + + QObject::connect(reply, &QNetworkReply::finished, [=] { + reply->deleteLater(); + + auto all = reply->readAll(); + auto parsed = json::parse(all.toStdString(), nullptr, false); + + if (reply->error() != QNetworkReply::NoError) { + qDebug() << QString::fromStdString(parsed.dump()); + qDebug() << reply->errorString(); + + (*responses)[item] = json::object(); // Empty object + } else { + if (parsed.is_discarded()) { + (*responses)[item] = json::object(); // Empty object + } else { + (*responses)[item] = parsed["result"]; + } + } + }); + } + + auto waitTimer = new QTimer(main); + QObject::connect(waitTimer, &QTimer::timeout, [=]() { + if (responses->size() == totalSize) { + waitTimer->stop(); + + cb(responses); + + waitTimer->deleteLater(); + } + }); + waitTimer->start(100); + } + + + private: void doRPC (const json& payload, const std::function& cb); void doSendRPC (const json& payload, const std::function& cb); @@ -71,11 +120,6 @@ private: void handleConnectionError (const QString& error); void handleTxError (const QString& error); - // Batch - void getBatchRPC(const QList& payloads, - std::function payloadGenerator, - std::function*)> cb); - QNetworkAccessManager* restclient; QNetworkRequest request; diff --git a/src/turnstile.cpp b/src/turnstile.cpp index a4f8f94..9385ba8 100644 --- a/src/turnstile.cpp +++ b/src/turnstile.cpp @@ -1,14 +1,125 @@ #include "turnstile.h" - +#include "rpc.h" #include "utils.h" +#include "settings.h" -Turnstile::Turnstile() { +#include "precompiled.h" + +using json = nlohmann::json; + +Turnstile::Turnstile(RPC* _rpc) { + this->rpc = _rpc; } - Turnstile::~Turnstile() { } +QString Turnstile::writeableFile() { + auto filename = QStringLiteral("turnstilemigrationplan.dat"); + + auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); + if (!dir.exists()) + QDir().mkpath(dir.absolutePath()); + + if (Settings::getInstance()->isTestnet()) { + return dir.filePath("testnet-" % filename); + } else { + return dir.filePath(filename); + } +} + +// Data stream write/read methods for migration items +QDataStream &operator<<(QDataStream& ds, const TurnstileMigrationItem& item) { + return ds << "v1" << item.fromAddr << item.intTAddr + << item.destAddr << item.amount << item.blockNumber << item.chaff; +} + +QDataStream &operator>>(QDataStream& ds, TurnstileMigrationItem& item) { + QString version; + return ds >> version >> item.fromAddr >> item.intTAddr + >> item.destAddr >> item.amount >> item.blockNumber >> item.chaff; +} + +void Turnstile::writeMigrationPlan(QList plan) { + QFile file(writeableFile()); + file.open(QIODevice::WriteOnly); + QDataStream out(&file); // we will serialize the data into the file + out << plan; +} + +QList Turnstile::readMigrationPlan() { + QFile file(writeableFile()); + + QList plan; + if (!file.exists()) return plan; + + file.open(QIODevice::ReadOnly); + QDataStream in(&file); // read the data serialized from the file + in >> plan; + + return plan; +} + +void Turnstile::planMigration(QString zaddr, QString destAddr) { + // First, get the balance and split up the amounts + auto bal = rpc->getAllBalances()->value(zaddr); + auto splits = splitAmount(bal+2354, 5); + + // Then, generate an intermediate t-Address for each part using getBatchRPC + rpc->getBatchRPC(splits, + [=] (double /*unused*/) { + json payload = { + {"jsonrpc", "1.0"}, + {"id", "someid"}, + {"method", "getnewaddress"}, + }; + return payload; + }, + [=] (QMap* newAddrs) { + // Get block numbers + auto curBlock = Settings::getInstance()->getBlockNumber(); + auto blockNumbers = getBlockNumbers(curBlock, curBlock + 10, splits.size()); + + // Assign the amounts to the addresses. + QList migItems; + + for (int i=0; i < splits.size(); i++) { + auto tAddr = newAddrs->values()[i].get(); + auto item = TurnstileMigrationItem { zaddr, QString::fromStdString(tAddr), destAddr, + blockNumbers[i], splits[i], i == splits.size() -1 }; + migItems.push_back(item); + } + + std::sort(migItems.begin(), migItems.end(), [&] (auto a, auto b) { + return a.blockNumber < b.blockNumber; + }); + + // The first migration is shifted to the current block, so the user sees something + // happening immediately + migItems[0].blockNumber = curBlock; + + writeMigrationPlan(migItems); + auto readPlan = readMigrationPlan(); + + for (auto item : readPlan) { + qDebug() << item.fromAddr << item.intTAddr + << item.destAddr << item.amount << item.blockNumber << item.chaff; + } + } + ); +} + +QList Turnstile::getBlockNumbers(int start, int end, int count) { + QList blocks; + // Generate 'count' numbers between [start, end] + for (int i=0; i < count; i++) { + auto blk = (std::rand() % (end - start)) + start; + blocks.push_back(blk); + } + + return blocks; +} + QList Turnstile::splitAmount(double amount, int parts) { QList amounts; // Need at least 0.0004 ZEC for this diff --git a/src/turnstile.h b/src/turnstile.h index 7a4bac7..427634b 100644 --- a/src/turnstile.h +++ b/src/turnstile.h @@ -1,16 +1,37 @@ #ifndef TURNSTILE_H #define TURNSTILE_H + #include "precompiled.h" +class RPC; + +struct TurnstileMigrationItem { + QString fromAddr; + QString intTAddr; + QString destAddr; + int blockNumber; + double amount; + bool chaff; +}; + class Turnstile { public: - Turnstile(); + Turnstile(RPC* _rpc); ~Turnstile(); + void planMigration(QString zaddr, QString destAddr); QList splitAmount(double amount, int parts); void fillAmounts(QList& amounts, double amount, int count); + + void writeMigrationPlan(QList plan); + QList readMigrationPlan(); + +private: + QList getBlockNumbers(int start, int end, int count); + QString writeableFile(); + RPC* rpc; }; #endif \ No newline at end of file diff --git a/zec-qt-wallet.pro b/zec-qt-wallet.pro index 7ae1f78..1b40335 100644 --- a/zec-qt-wallet.pro +++ b/zec-qt-wallet.pro @@ -13,7 +13,7 @@ PRECOMPILED_HEADER = src/precompiled.h greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = zec-qt-wallet -APP_VERSION=\\\"0.2.2\\\" +APP_VERSION=\\\"0.2.3\\\" TEMPLATE = app From 9c292519d4bc27a573b2a073a4841041ec9b952c Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Mon, 22 Oct 2018 22:10:52 -0700 Subject: [PATCH 11/25] Turnstile prototype --- src/mainwindow.cpp | 35 ++++++ src/mainwindow.ui | 12 ++ src/turnstile.ui | 229 +++++++++++++++++++++++++++++++++++++ src/turnstileprogress.ui | 154 +++++++++++++++++++++++++ src/ui_mainwindow.h | 10 ++ src/ui_turnstile.h | 210 ++++++++++++++++++++++++++++++++++ src/ui_turnstileprogress.h | 141 +++++++++++++++++++++++ zec-qt-wallet.pro | 4 +- 8 files changed, 794 insertions(+), 1 deletion(-) create mode 100644 src/turnstile.ui create mode 100644 src/turnstileprogress.ui create mode 100644 src/ui_turnstile.h create mode 100644 src/ui_turnstileprogress.h diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2606f6d..d03c0a6 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2,12 +2,15 @@ #include "ui_mainwindow.h" #include "ui_about.h" #include "ui_settings.h" +#include "ui_turnstile.h" +#include "ui_turnstileprogress.h" #include "rpc.h" #include "balancestablemodel.h" #include "settings.h" #include "utils.h" #include "senttxstore.h" + #include "precompiled.h" using json = nlohmann::json; @@ -24,6 +27,38 @@ MainWindow::MainWindow(QWidget *parent) : // Settings editor setupSettingsModal(); + // Turnstile migration + QObject::connect(ui->actionTurnstile_Migration, &QAction::triggered, [=] () { + Ui_Turnstile turnstile; + QDialog d(this); + turnstile.setupUi(&d); + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); + turnstile.msgIcon->setPixmap(icon.pixmap(64, 64)); + + turnstile.migrateZaddList->addItem("All Sprout z-Addrs"); + turnstile.migrateTo->addItem("zs1gv64eu0v2wx7raxqxlmj354y9ycznwaau9kduljzczxztvs4qcl00kn2sjxtejvrxnkucw5xx9u"); + turnstile.privLevel->addItem("Good - 3 tx over 3 days"); + turnstile.privLevel->addItem("Excellent - 5 tx over 5 days"); + turnstile.privLevel->addItem("Paranoid - 10 tx over 7 days"); + + turnstile.buttonBox->button(QDialogButtonBox::Ok)->setText("Start"); + + d.exec(); + }); + + QObject::connect(ui->actionProgress, &QAction::triggered, [=] () { + Ui_TurnstileProgress progress; + QDialog d(this); + progress.setupUi(&d); + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning); + progress.msgIcon->setPixmap(icon.pixmap(64, 64)); + + progress.buttonBox->button(QDialogButtonBox::Cancel)->setText("Abort"); + d.exec(); + }); + // Set up exit action QObject::connect(ui->actionExit, &QAction::triggered, this, &MainWindow::close); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 4baf922..9e408c4 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -720,6 +720,8 @@ File + + @@ -769,6 +771,16 @@ Check github.com for Updates + + + Turnstile Migration + + + + + Progress + + diff --git a/src/turnstile.ui b/src/turnstile.ui new file mode 100644 index 0000000..a12af05 --- /dev/null +++ b/src/turnstile.ui @@ -0,0 +1,229 @@ + + + Turnstile + + + + 0 + 0 + 565 + 416 + + + + Turnstile Migration + + + + + + Turnstile Migration + + + + + + + + + + + Qt::AlignCenter + + + + + + + Total Fees + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + Privacy Level + + + + + + + + 0 + 0 + + + + Miner Fee: + + + + + + + + 0 + 0 + + + + From + + + + + + + + 0 + 0 + + + + Dev Fee: + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 0.0004 ZEC $0.04 + + + + + + + 0.0004 ZEC $0.04 + + + + + + + + 0 + 0 + + + + false + + + + + + + + + + + 0 + 0 + + + + + + + + <html><head/><body><p>Funds from Sprout z-Addresses (which start with &quot;zc&quot;) need to be moved to the upgraded Sapling z-Addresses (which start with &quot;zs&quot;). The funds cannot be moved directly, but need to be sent through intermediate &quot;transparent&quot; addresses in privacy-preserving way.</p><p>This migration can be done automatically for you.</p></body></html> + + + true + + + + + + + + 0 + 0 + + + + To + + + + + + + + + + Qt::Horizontal + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + Turnstile + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Turnstile + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/turnstileprogress.ui b/src/turnstileprogress.ui new file mode 100644 index 0000000..5b09ebd --- /dev/null +++ b/src/turnstileprogress.ui @@ -0,0 +1,154 @@ + + + TurnstileProgress + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + + 33 + + + + + + + + 0 + 0 + + + + Please Ensure you have your wallet.dat backed up! + + + true + + + + + + + Qt::Horizontal + + + + + + + Next Transaction in 4 hours + + + + + + + 4 / 12 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Migration Progress + + + + + + + + 0 + 0 + + + + TextLabel + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + + + + + + buttonBox + accepted() + TurnstileProgress + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + TurnstileProgress + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/ui_mainwindow.h b/src/ui_mainwindow.h index c9a29ea..ac1195a 100644 --- a/src/ui_mainwindow.h +++ b/src/ui_mainwindow.h @@ -47,6 +47,8 @@ public: QAction *actionDonate; QAction *actionImport_Private_Keys; QAction *actionCheck_for_Updates; + QAction *actionTurnstile_Migration; + QAction *actionProgress; QWidget *centralWidget; QGridLayout *gridLayout_3; QTabWidget *tabWidget; @@ -159,6 +161,10 @@ public: actionImport_Private_Keys->setVisible(false); actionCheck_for_Updates = new QAction(MainWindow); actionCheck_for_Updates->setObjectName(QStringLiteral("actionCheck_for_Updates")); + actionTurnstile_Migration = new QAction(MainWindow); + actionTurnstile_Migration->setObjectName(QStringLiteral("actionTurnstile_Migration")); + actionProgress = new QAction(MainWindow); + actionProgress->setObjectName(QStringLiteral("actionProgress")); centralWidget = new QWidget(MainWindow); centralWidget->setObjectName(QStringLiteral("centralWidget")); gridLayout_3 = new QGridLayout(centralWidget); @@ -666,6 +672,8 @@ public: menuBar->addAction(menuBalance->menuAction()); menuBar->addAction(menuHelp->menuAction()); menuBalance->addAction(actionImport_Private_Keys); + menuBalance->addAction(actionTurnstile_Migration); + menuBalance->addAction(actionProgress); menuBalance->addAction(actionSettings); menuBalance->addSeparator(); menuBalance->addAction(actionExit); @@ -690,6 +698,8 @@ public: actionDonate->setText(QApplication::translate("MainWindow", "Donate", nullptr)); actionImport_Private_Keys->setText(QApplication::translate("MainWindow", "Import Private Keys", nullptr)); actionCheck_for_Updates->setText(QApplication::translate("MainWindow", "Check github.com for Updates", nullptr)); + actionTurnstile_Migration->setText(QApplication::translate("MainWindow", "Turnstile Migration", nullptr)); + actionProgress->setText(QApplication::translate("MainWindow", "Progress", nullptr)); groupBox->setTitle(QApplication::translate("MainWindow", "Summary", nullptr)); label->setText(QApplication::translate("MainWindow", "Shielded", nullptr)); balSheilded->setText(QString()); diff --git a/src/ui_turnstile.h b/src/ui_turnstile.h new file mode 100644 index 0000000..8eb3566 --- /dev/null +++ b/src/ui_turnstile.h @@ -0,0 +1,210 @@ +/******************************************************************************** +** Form generated from reading UI file 'turnstile.ui' +** +** Created by: Qt User Interface Compiler version 5.11.2 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_TURNSTILE_H +#define UI_TURNSTILE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_Turnstile +{ +public: + QVBoxLayout *verticalLayout; + QGroupBox *groupBox; + QVBoxLayout *verticalLayout_2; + QGridLayout *gridLayout; + QLabel *msgIcon; + QLabel *label_3; + QLabel *label_2; + QLabel *label_4; + QLabel *label; + QLabel *label_5; + QSpacerItem *verticalSpacer; + QLabel *label_6; + QLabel *label_7; + QComboBox *migrateZaddList; + QComboBox *privLevel; + QLabel *label_8; + QLabel *label_9; + QComboBox *migrateTo; + QFrame *line; + QDialogButtonBox *buttonBox; + + void setupUi(QDialog *Turnstile) + { + if (Turnstile->objectName().isEmpty()) + Turnstile->setObjectName(QStringLiteral("Turnstile")); + Turnstile->resize(565, 416); + verticalLayout = new QVBoxLayout(Turnstile); + verticalLayout->setObjectName(QStringLiteral("verticalLayout")); + groupBox = new QGroupBox(Turnstile); + groupBox->setObjectName(QStringLiteral("groupBox")); + verticalLayout_2 = new QVBoxLayout(groupBox); + verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2")); + gridLayout = new QGridLayout(); + gridLayout->setObjectName(QStringLiteral("gridLayout")); + msgIcon = new QLabel(groupBox); + msgIcon->setObjectName(QStringLiteral("msgIcon")); + msgIcon->setAlignment(Qt::AlignCenter); + + gridLayout->addWidget(msgIcon, 0, 0, 1, 1); + + label_3 = new QLabel(groupBox); + label_3->setObjectName(QStringLiteral("label_3")); + label_3->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop); + + gridLayout->addWidget(label_3, 5, 0, 2, 1); + + label_2 = new QLabel(groupBox); + label_2->setObjectName(QStringLiteral("label_2")); + + gridLayout->addWidget(label_2, 4, 0, 1, 1); + + label_4 = new QLabel(groupBox); + label_4->setObjectName(QStringLiteral("label_4")); + QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(label_4->sizePolicy().hasHeightForWidth()); + label_4->setSizePolicy(sizePolicy); + + gridLayout->addWidget(label_4, 5, 1, 1, 1); + + label = new QLabel(groupBox); + label->setObjectName(QStringLiteral("label")); + QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Preferred); + sizePolicy1.setHorizontalStretch(0); + sizePolicy1.setVerticalStretch(0); + sizePolicy1.setHeightForWidth(label->sizePolicy().hasHeightForWidth()); + label->setSizePolicy(sizePolicy1); + + gridLayout->addWidget(label, 2, 0, 1, 1); + + label_5 = new QLabel(groupBox); + label_5->setObjectName(QStringLiteral("label_5")); + sizePolicy.setHeightForWidth(label_5->sizePolicy().hasHeightForWidth()); + label_5->setSizePolicy(sizePolicy); + + gridLayout->addWidget(label_5, 6, 1, 1, 1); + + verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + gridLayout->addItem(verticalSpacer, 7, 0, 1, 2); + + label_6 = new QLabel(groupBox); + label_6->setObjectName(QStringLiteral("label_6")); + + gridLayout->addWidget(label_6, 5, 2, 1, 1); + + label_7 = new QLabel(groupBox); + label_7->setObjectName(QStringLiteral("label_7")); + + gridLayout->addWidget(label_7, 6, 2, 1, 1); + + migrateZaddList = new QComboBox(groupBox); + migrateZaddList->setObjectName(QStringLiteral("migrateZaddList")); + QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Fixed); + sizePolicy2.setHorizontalStretch(0); + sizePolicy2.setVerticalStretch(0); + sizePolicy2.setHeightForWidth(migrateZaddList->sizePolicy().hasHeightForWidth()); + migrateZaddList->setSizePolicy(sizePolicy2); + migrateZaddList->setEditable(false); + + gridLayout->addWidget(migrateZaddList, 2, 1, 1, 2); + + privLevel = new QComboBox(groupBox); + privLevel->setObjectName(QStringLiteral("privLevel")); + sizePolicy2.setHeightForWidth(privLevel->sizePolicy().hasHeightForWidth()); + privLevel->setSizePolicy(sizePolicy2); + + gridLayout->addWidget(privLevel, 4, 1, 1, 2); + + label_8 = new QLabel(groupBox); + label_8->setObjectName(QStringLiteral("label_8")); + label_8->setWordWrap(true); + + gridLayout->addWidget(label_8, 0, 1, 1, 2); + + label_9 = new QLabel(groupBox); + label_9->setObjectName(QStringLiteral("label_9")); + sizePolicy1.setHeightForWidth(label_9->sizePolicy().hasHeightForWidth()); + label_9->setSizePolicy(sizePolicy1); + + gridLayout->addWidget(label_9, 3, 0, 1, 1); + + migrateTo = new QComboBox(groupBox); + migrateTo->setObjectName(QStringLiteral("migrateTo")); + + gridLayout->addWidget(migrateTo, 3, 1, 1, 2); + + line = new QFrame(groupBox); + line->setObjectName(QStringLiteral("line")); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + + gridLayout->addWidget(line, 1, 0, 1, 3); + + + verticalLayout_2->addLayout(gridLayout); + + + verticalLayout->addWidget(groupBox); + + buttonBox = new QDialogButtonBox(Turnstile); + buttonBox->setObjectName(QStringLiteral("buttonBox")); + buttonBox->setOrientation(Qt::Horizontal); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + + verticalLayout->addWidget(buttonBox); + + + retranslateUi(Turnstile); + QObject::connect(buttonBox, SIGNAL(accepted()), Turnstile, SLOT(accept())); + QObject::connect(buttonBox, SIGNAL(rejected()), Turnstile, SLOT(reject())); + + QMetaObject::connectSlotsByName(Turnstile); + } // setupUi + + void retranslateUi(QDialog *Turnstile) + { + Turnstile->setWindowTitle(QApplication::translate("Turnstile", "Turnstile Migration", nullptr)); + groupBox->setTitle(QApplication::translate("Turnstile", "Turnstile Migration", nullptr)); + msgIcon->setText(QString()); + label_3->setText(QApplication::translate("Turnstile", "Total Fees", nullptr)); + label_2->setText(QApplication::translate("Turnstile", "Privacy Level", nullptr)); + label_4->setText(QApplication::translate("Turnstile", "Miner Fee:", nullptr)); + label->setText(QApplication::translate("Turnstile", "From", nullptr)); + label_5->setText(QApplication::translate("Turnstile", "Dev Fee: ", nullptr)); + label_6->setText(QApplication::translate("Turnstile", "0.0004 ZEC $0.04", nullptr)); + label_7->setText(QApplication::translate("Turnstile", "0.0004 ZEC $0.04", nullptr)); + migrateZaddList->setCurrentText(QString()); + label_8->setText(QApplication::translate("Turnstile", "

Funds from Sprout z-Addresses (which start with "zc") need to be moved to the upgraded Sapling z-Addresses (which start with "zs"). The funds cannot be moved directly, but need to be sent through intermediate "transparent" addresses in privacy-preserving way.

This migration can be done automatically for you.

", nullptr)); + label_9->setText(QApplication::translate("Turnstile", "To", nullptr)); + } // retranslateUi + +}; + +namespace Ui { + class Turnstile: public Ui_Turnstile {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_TURNSTILE_H diff --git a/src/ui_turnstileprogress.h b/src/ui_turnstileprogress.h new file mode 100644 index 0000000..2d34909 --- /dev/null +++ b/src/ui_turnstileprogress.h @@ -0,0 +1,141 @@ +/******************************************************************************** +** Form generated from reading UI file 'turnstileprogress.ui' +** +** Created by: Qt User Interface Compiler version 5.11.2 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_TURNSTILEPROGRESS_H +#define UI_TURNSTILEPROGRESS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_TurnstileProgress +{ +public: + QGridLayout *gridLayout; + QProgressBar *progressBar; + QLabel *label_4; + QFrame *line; + QLabel *label; + QLabel *label_3; + QLabel *label_2; + QLabel *msgIcon; + QDialogButtonBox *buttonBox; + QSpacerItem *verticalSpacer; + QFrame *line_2; + + void setupUi(QDialog *TurnstileProgress) + { + if (TurnstileProgress->objectName().isEmpty()) + TurnstileProgress->setObjectName(QStringLiteral("TurnstileProgress")); + TurnstileProgress->resize(400, 300); + gridLayout = new QGridLayout(TurnstileProgress); + gridLayout->setObjectName(QStringLiteral("gridLayout")); + progressBar = new QProgressBar(TurnstileProgress); + progressBar->setObjectName(QStringLiteral("progressBar")); + progressBar->setValue(33); + + gridLayout->addWidget(progressBar, 3, 0, 1, 3); + + label_4 = new QLabel(TurnstileProgress); + label_4->setObjectName(QStringLiteral("label_4")); + QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(label_4->sizePolicy().hasHeightForWidth()); + label_4->setSizePolicy(sizePolicy); + label_4->setWordWrap(true); + + gridLayout->addWidget(label_4, 7, 1, 1, 2); + + line = new QFrame(TurnstileProgress); + line->setObjectName(QStringLiteral("line")); + line->setFrameShape(QFrame::HLine); + line->setFrameShadow(QFrame::Sunken); + + gridLayout->addWidget(line, 4, 0, 1, 3); + + label = new QLabel(TurnstileProgress); + label->setObjectName(QStringLiteral("label")); + + gridLayout->addWidget(label, 5, 0, 1, 3); + + label_3 = new QLabel(TurnstileProgress); + label_3->setObjectName(QStringLiteral("label_3")); + label_3->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout->addWidget(label_3, 2, 2, 1, 1); + + label_2 = new QLabel(TurnstileProgress); + label_2->setObjectName(QStringLiteral("label_2")); + + gridLayout->addWidget(label_2, 2, 0, 1, 2); + + msgIcon = new QLabel(TurnstileProgress); + msgIcon->setObjectName(QStringLiteral("msgIcon")); + QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Preferred); + sizePolicy1.setHorizontalStretch(0); + sizePolicy1.setVerticalStretch(0); + sizePolicy1.setHeightForWidth(msgIcon->sizePolicy().hasHeightForWidth()); + msgIcon->setSizePolicy(sizePolicy1); + msgIcon->setAlignment(Qt::AlignCenter); + + gridLayout->addWidget(msgIcon, 7, 0, 1, 1); + + buttonBox = new QDialogButtonBox(TurnstileProgress); + buttonBox->setObjectName(QStringLiteral("buttonBox")); + buttonBox->setOrientation(Qt::Horizontal); + buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); + + gridLayout->addWidget(buttonBox, 9, 0, 1, 3); + + verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + gridLayout->addItem(verticalSpacer, 6, 0, 1, 3); + + line_2 = new QFrame(TurnstileProgress); + line_2->setObjectName(QStringLiteral("line_2")); + line_2->setFrameShape(QFrame::HLine); + line_2->setFrameShadow(QFrame::Sunken); + + gridLayout->addWidget(line_2, 8, 0, 1, 3); + + + retranslateUi(TurnstileProgress); + QObject::connect(buttonBox, SIGNAL(accepted()), TurnstileProgress, SLOT(accept())); + QObject::connect(buttonBox, SIGNAL(rejected()), TurnstileProgress, SLOT(reject())); + + QMetaObject::connectSlotsByName(TurnstileProgress); + } // setupUi + + void retranslateUi(QDialog *TurnstileProgress) + { + TurnstileProgress->setWindowTitle(QApplication::translate("TurnstileProgress", "Dialog", nullptr)); + label_4->setText(QApplication::translate("TurnstileProgress", "Please Ensure you have your wallet.dat backed up!", nullptr)); + label->setText(QApplication::translate("TurnstileProgress", "Next Transaction in 4 hours", nullptr)); + label_3->setText(QApplication::translate("TurnstileProgress", "4 / 12", nullptr)); + label_2->setText(QApplication::translate("TurnstileProgress", "Migration Progress", nullptr)); + msgIcon->setText(QApplication::translate("TurnstileProgress", "TextLabel", nullptr)); + } // retranslateUi + +}; + +namespace Ui { + class TurnstileProgress: public Ui_TurnstileProgress {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_TURNSTILEPROGRESS_H diff --git a/zec-qt-wallet.pro b/zec-qt-wallet.pro index c483f19..710aafa 100644 --- a/zec-qt-wallet.pro +++ b/zec-qt-wallet.pro @@ -71,7 +71,9 @@ FORMS += \ src/mainwindow.ui \ src/settings.ui \ src/about.ui \ - src/confirm.ui + src/confirm.ui \ + src/turnstile.ui \ + src/turnstileprogress.ui # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin From 8e0b118cc673189999f303967d6fdb3b7354bd6a Mon Sep 17 00:00:00 2001 From: adityapk00 Date: Wed, 24 Oct 2018 21:06:03 -0700 Subject: [PATCH 12/25] intermediate checkin --- src/main.cpp | 8 ++++++++ src/precompiled.h | 2 ++ src/turnstile.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/turnstile.h | 11 +++++++++++ zec-qt-wallet.pro | 2 ++ 5 files changed, 60 insertions(+) create mode 100644 src/turnstile.cpp create mode 100644 src/turnstile.h diff --git a/src/main.cpp b/src/main.cpp index 76b6873..f96df19 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,7 @@ #include "mainwindow.h" #include "settings.h" +#include "turnstile.h" + #include "precompiled.h" int main(int argc, char *argv[]) @@ -16,6 +18,8 @@ int main(int argc, char *argv[]) qApp->setFont(QFont("Ubuntu", 11, QFont::Normal, false)); #endif + std::srand(std::time(nullptr)); + QCoreApplication::setOrganizationName("zec-qt-wallet-org"); QCoreApplication::setApplicationName("zec-qt-wallet"); @@ -24,6 +28,10 @@ int main(int argc, char *argv[]) MainWindow w; w.setWindowTitle("zec-qt-wallet v" + QString(APP_VERSION)); w.show(); + + // Temp + Turnstile t; + qDebug() << t.splitAmount(1245.2294371, 3); return QApplication::exec(); } diff --git a/src/precompiled.h b/src/precompiled.h index c3e837b..976fba1 100644 --- a/src/precompiled.h +++ b/src/precompiled.h @@ -2,6 +2,8 @@ /* Add C++ includes here */ #include +#include +#include #include #include diff --git a/src/turnstile.cpp b/src/turnstile.cpp new file mode 100644 index 0000000..c442d70 --- /dev/null +++ b/src/turnstile.cpp @@ -0,0 +1,37 @@ +#include "precompiled.h" +#include "turnstile.h" + + +Turnstile::Turnstile() { +} + + +Turnstile::~Turnstile() { +} + +QList Turnstile::splitAmount(double amount, int parts) { + QList amounts; + fillAmounts(amounts, amount, parts); + + // Ensure they all add up! + double sumofparts = 0; + for (auto a : amounts) { + sumofparts += a.toDouble(); + } + + Q_ASSERT(sumofparts == amount); + return amounts; +} + +void Turnstile::fillAmounts(QList& amounts, double amount, int count) { + if (count == 1 || amount < 1) { + amounts.push_back(QString::number(amount, 'g', 8)); + return; + } + + // Get a random amount off the amount and call recursively. + auto curAmount = std::rand() % (int)std::floor(amount); + amounts.push_back(QString::number(curAmount, 'g', 8)); + + fillAmounts(amounts, amount - curAmount, count - 1); +} \ No newline at end of file diff --git a/src/turnstile.h b/src/turnstile.h new file mode 100644 index 0000000..0da7098 --- /dev/null +++ b/src/turnstile.h @@ -0,0 +1,11 @@ +#pragma once +class Turnstile +{ +public: + Turnstile(); + ~Turnstile(); + + QList Turnstile::splitAmount(double amount, int parts); + void fillAmounts(QList& amounts, double amount, int count); +}; + diff --git a/zec-qt-wallet.pro b/zec-qt-wallet.pro index 710aafa..1b40335 100644 --- a/zec-qt-wallet.pro +++ b/zec-qt-wallet.pro @@ -50,6 +50,7 @@ SOURCES += \ src/sendtab.cpp \ src/senttxstore.cpp \ src/txtablemodel.cpp \ + src/turnstile.cpp \ src/utils.cpp HEADERS += \ @@ -65,6 +66,7 @@ HEADERS += \ src/settings.h \ src/txtablemodel.h \ src/senttxstore.h \ + src/turnstile.h \ src/utils.h FORMS += \ From 77423568423c43b2a92b0bb36ecd170c133680f5 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Wed, 24 Oct 2018 22:28:55 -0700 Subject: [PATCH 13/25] Split up amounts --- src/main.cpp | 6 +++++- src/mainwindow.cpp | 1 - src/precompiled.h | 1 + src/turnstile.cpp | 40 ++++++++++++++++++++++++++++++++-------- src/turnstile.h | 11 ++++++++--- 5 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index f96df19..b73e119 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,7 +31,11 @@ int main(int argc, char *argv[]) // Temp Turnstile t; - qDebug() << t.splitAmount(1245.2294371, 3); + double amt = 2329127.99999999; + qDebug() << QString::number(amt, 'f', 8) << ":"; + for (auto a : t.splitAmount(amt, 3)) { + qDebug() << QString::number(a, 'f', 8); + } return QApplication::exec(); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d03c0a6..9816d6a 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -10,7 +10,6 @@ #include "utils.h" #include "senttxstore.h" - #include "precompiled.h" using json = nlohmann::json; diff --git a/src/precompiled.h b/src/precompiled.h index 976fba1..552226d 100644 --- a/src/precompiled.h +++ b/src/precompiled.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include diff --git a/src/turnstile.cpp b/src/turnstile.cpp index c442d70..bb15260 100644 --- a/src/turnstile.cpp +++ b/src/turnstile.cpp @@ -1,6 +1,6 @@ -#include "precompiled.h" #include "turnstile.h" +#include "utils.h" Turnstile::Turnstile() { } @@ -9,29 +9,53 @@ Turnstile::Turnstile() { Turnstile::~Turnstile() { } -QList Turnstile::splitAmount(double amount, int parts) { - QList amounts; +QList Turnstile::splitAmount(double amount, int parts) { + QList amounts; fillAmounts(amounts, amount, parts); // Ensure they all add up! double sumofparts = 0; for (auto a : amounts) { - sumofparts += a.toDouble(); + sumofparts += a; } Q_ASSERT(sumofparts == amount); return amounts; } -void Turnstile::fillAmounts(QList& amounts, double amount, int count) { +void Turnstile::fillAmounts(QList& amounts, double amount, int count) { if (count == 1 || amount < 1) { - amounts.push_back(QString::number(amount, 'g', 8)); + // Split the chaff. + // Chaff is all amounts lesser than 0.0001 ZEC. The chaff will be added to the + // dev fee, and is done so to protect privacy. + + // Get the rounded value to 4 decimal places (approx $0.01) + double actual = std::floor(amount * 10000) / 10000; + + // Reduce the Dev Tx fee from the amount + actual = actual - 0.0001; //Utils::getDevFee(); + + // Calculate the chaff. + double chaff = amount - actual; + + amounts.push_back(actual); + if (chaff > 0.00000001) // zcash is split down to 8 decimal places + amounts.push_back(chaff); return; } - // Get a random amount off the amount and call recursively. + // Get a random amount off the amount (between half and full) and call recursively. auto curAmount = std::rand() % (int)std::floor(amount); - amounts.push_back(QString::number(curAmount, 'g', 8)); + + // Try to round it off + if (curAmount > 1000) { + curAmount = std::floor(curAmount / 100) * 100; + } else if (curAmount > 100) { + curAmount = std::floor(curAmount / 10) * 10; + } + + if (curAmount > 0) + amounts.push_back(curAmount); fillAmounts(amounts, amount - curAmount, count - 1); } \ No newline at end of file diff --git a/src/turnstile.h b/src/turnstile.h index 0da7098..7a4bac7 100644 --- a/src/turnstile.h +++ b/src/turnstile.h @@ -1,11 +1,16 @@ -#pragma once +#ifndef TURNSTILE_H +#define TURNSTILE_H + +#include "precompiled.h" + class Turnstile { public: Turnstile(); ~Turnstile(); - QList Turnstile::splitAmount(double amount, int parts); - void fillAmounts(QList& amounts, double amount, int count); + QList splitAmount(double amount, int parts); + void fillAmounts(QList& amounts, double amount, int count); }; +#endif \ No newline at end of file From e28a4d9c9ab88e44ffaa4a33b0a32097fe56e7d8 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Wed, 24 Oct 2018 22:33:45 -0700 Subject: [PATCH 14/25] Account for tx fees --- src/turnstile.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/turnstile.cpp b/src/turnstile.cpp index bb15260..349db59 100644 --- a/src/turnstile.cpp +++ b/src/turnstile.cpp @@ -35,6 +35,9 @@ void Turnstile::fillAmounts(QList& amounts, double amount, int count) { // Reduce the Dev Tx fee from the amount actual = actual - 0.0001; //Utils::getDevFee(); + // Also account for the fees needed to send all these transactions + actual = actual - (Utils::getMinerFee() * (amounts.size() + 1)); + // Calculate the chaff. double chaff = amount - actual; From 9a0c368623dc2d2f1fc9a9e6132f1abbc2df0e5f Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Wed, 24 Oct 2018 22:44:45 -0700 Subject: [PATCH 15/25] Add min --- src/turnstile.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/turnstile.cpp b/src/turnstile.cpp index 349db59..a4f8f94 100644 --- a/src/turnstile.cpp +++ b/src/turnstile.cpp @@ -11,6 +11,10 @@ Turnstile::~Turnstile() { QList Turnstile::splitAmount(double amount, int parts) { QList amounts; + // Need at least 0.0004 ZEC for this + if (amount < 0.0004) + return amounts; + fillAmounts(amounts, amount, parts); // Ensure they all add up! From c87f9aea85cce7e7b42659512ff4443dad46fa7b Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Thu, 25 Oct 2018 09:44:40 -0700 Subject: [PATCH 16/25] minor --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index b73e119..96581a4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,7 +31,7 @@ int main(int argc, char *argv[]) // Temp Turnstile t; - double amt = 2329127.99999999; + double amt = 0.0003; qDebug() << QString::number(amt, 'f', 8) << ":"; for (auto a : t.splitAmount(amt, 3)) { qDebug() << QString::number(a, 'f', 8); From f39722eb69f9cec76f58ab6c46faf158876e1c35 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Thu, 25 Oct 2018 11:52:02 -0700 Subject: [PATCH 17/25] create migration plan --- src/main.cpp | 8 ---- src/rpc.cpp | 61 ++++-------------------- src/rpc.h | 54 +++++++++++++++++++-- src/turnstile.cpp | 117 ++++++++++++++++++++++++++++++++++++++++++++-- src/turnstile.h | 23 ++++++++- 5 files changed, 195 insertions(+), 68 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 96581a4..c86c2af 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,14 +28,6 @@ int main(int argc, char *argv[]) MainWindow w; w.setWindowTitle("zec-qt-wallet v" + QString(APP_VERSION)); w.show(); - - // Temp - Turnstile t; - double amt = 0.0003; - qDebug() << QString::number(amt, 'f', 8) << ":"; - for (auto a : t.splitAmount(amt, 3)) { - qDebug() << QString::number(a, 'f', 8); - } return QApplication::exec(); } diff --git a/src/rpc.cpp b/src/rpc.cpp index 5dce998..c70a6f1 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -2,6 +2,7 @@ #include "utils.h" #include "settings.h" #include "senttxstore.h" +#include "turnstile.h" using json = nlohmann::json; @@ -46,6 +47,7 @@ RPC::RPC(QNetworkAccessManager* client, MainWindow* main) { }); // Start at every 10s. When an operation is pending, this will change to every second txTimer->start(Utils::updateSpeed); + } RPC::~RPC() { @@ -284,54 +286,6 @@ void RPC::handleTxError(const QString& error) { msg.exec(); } - -void RPC::getBatchRPC( - const QList& payloads, - std::function payloadGenerator, - std::function*)> cb) -{ - auto responses = new QMap(); // zAddr -> list of responses for each call. - int totalSize = payloads.size(); - - for (auto item: payloads) { - json payload = payloadGenerator(item); - - QNetworkReply *reply = restclient->post(request, QByteArray::fromStdString(payload.dump())); - - QObject::connect(reply, &QNetworkReply::finished, [=] { - reply->deleteLater(); - - auto all = reply->readAll(); - auto parsed = json::parse(all.toStdString(), nullptr, false); - - if (reply->error() != QNetworkReply::NoError) { - qDebug() << QString::fromStdString(parsed.dump()); - qDebug() << reply->errorString(); - - (*responses)[item] = json::object(); // Empty object - } else { - if (parsed.is_discarded()) { - (*responses)[item] = json::object(); // Empty object - } else { - (*responses)[item] = parsed["result"]; - } - } - }); - } - - auto waitTimer = new QTimer(main); - QObject::connect(waitTimer, &QTimer::timeout, [=]() { - if (responses->size() == totalSize) { - waitTimer->stop(); - - cb(responses); - - waitTimer->deleteLater(); - } - }); - waitTimer->start(100); -} - // Refresh received z txs by calling z_listreceivedbyaddress/gettransaction void RPC::refreshReceivedZTrans(QList zaddrs) { @@ -349,7 +303,7 @@ void RPC::refreshReceivedZTrans(QList zaddrs) { // and each z-Addr can have multiple received txs. // 1. For each z-Addr, get list of received txs - getBatchRPC(zaddrs, + getBatchRPC(zaddrs, [=] (QString zaddr) { json payload = { {"jsonrpc", "1.0"}, @@ -373,7 +327,7 @@ void RPC::refreshReceivedZTrans(QList zaddrs) { } // 2. For all txids, go and get the details of that txid. - getBatchRPC(txids.toList(), + getBatchRPC(txids.toList(), [=] (QString txid) { json payload = { {"jsonrpc", "1.0"}, @@ -507,6 +461,11 @@ void RPC::refreshAddresses() { // Function to create the data model and update the views, used below. void RPC::updateUI(bool anyUnconfirmed) { + + // Temp + Turnstile t(this); + t.planMigration(zaddresses->at(1), zaddresses->at(0)); + ui->unconfirmedWarning->setVisible(anyUnconfirmed); // Update balances model data, which will update the table too @@ -624,7 +583,7 @@ void RPC::refreshSentZTrans() { } // Look up all the txids to get the confirmation count for them. - getBatchRPC(txids, + getBatchRPC(txids, [=] (QString txid) { json payload = { {"jsonrpc", "1.0"}, diff --git a/src/rpc.h b/src/rpc.h index bdb903b..1bbd6fd 100644 --- a/src/rpc.h +++ b/src/rpc.h @@ -46,6 +46,55 @@ public: void newZaddr (bool sapling, const std::function& cb); void newTaddr (const std::function& cb); + // Batch method. Note: Because of the template, it has to be in the header file. + template + void getBatchRPC(const QList& payloads, + std::function payloadGenerator, + std::function*)> cb) { + auto responses = new QMap(); // zAddr -> list of responses for each call. + int totalSize = payloads.size(); + + for (auto item: payloads) { + json payload = payloadGenerator(item); + + QNetworkReply *reply = restclient->post(request, QByteArray::fromStdString(payload.dump())); + + QObject::connect(reply, &QNetworkReply::finished, [=] { + reply->deleteLater(); + + auto all = reply->readAll(); + auto parsed = json::parse(all.toStdString(), nullptr, false); + + if (reply->error() != QNetworkReply::NoError) { + qDebug() << QString::fromStdString(parsed.dump()); + qDebug() << reply->errorString(); + + (*responses)[item] = json::object(); // Empty object + } else { + if (parsed.is_discarded()) { + (*responses)[item] = json::object(); // Empty object + } else { + (*responses)[item] = parsed["result"]; + } + } + }); + } + + auto waitTimer = new QTimer(main); + QObject::connect(waitTimer, &QTimer::timeout, [=]() { + if (responses->size() == totalSize) { + waitTimer->stop(); + + cb(responses); + + waitTimer->deleteLater(); + } + }); + waitTimer->start(100); + } + + + private: void doRPC (const json& payload, const std::function& cb); void doSendRPC (const json& payload, const std::function& cb); @@ -71,11 +120,6 @@ private: void handleConnectionError (const QString& error); void handleTxError (const QString& error); - // Batch - void getBatchRPC(const QList& payloads, - std::function payloadGenerator, - std::function*)> cb); - QNetworkAccessManager* restclient; QNetworkRequest request; diff --git a/src/turnstile.cpp b/src/turnstile.cpp index a4f8f94..9385ba8 100644 --- a/src/turnstile.cpp +++ b/src/turnstile.cpp @@ -1,14 +1,125 @@ #include "turnstile.h" - +#include "rpc.h" #include "utils.h" +#include "settings.h" -Turnstile::Turnstile() { +#include "precompiled.h" + +using json = nlohmann::json; + +Turnstile::Turnstile(RPC* _rpc) { + this->rpc = _rpc; } - Turnstile::~Turnstile() { } +QString Turnstile::writeableFile() { + auto filename = QStringLiteral("turnstilemigrationplan.dat"); + + auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); + if (!dir.exists()) + QDir().mkpath(dir.absolutePath()); + + if (Settings::getInstance()->isTestnet()) { + return dir.filePath("testnet-" % filename); + } else { + return dir.filePath(filename); + } +} + +// Data stream write/read methods for migration items +QDataStream &operator<<(QDataStream& ds, const TurnstileMigrationItem& item) { + return ds << "v1" << item.fromAddr << item.intTAddr + << item.destAddr << item.amount << item.blockNumber << item.chaff; +} + +QDataStream &operator>>(QDataStream& ds, TurnstileMigrationItem& item) { + QString version; + return ds >> version >> item.fromAddr >> item.intTAddr + >> item.destAddr >> item.amount >> item.blockNumber >> item.chaff; +} + +void Turnstile::writeMigrationPlan(QList plan) { + QFile file(writeableFile()); + file.open(QIODevice::WriteOnly); + QDataStream out(&file); // we will serialize the data into the file + out << plan; +} + +QList Turnstile::readMigrationPlan() { + QFile file(writeableFile()); + + QList plan; + if (!file.exists()) return plan; + + file.open(QIODevice::ReadOnly); + QDataStream in(&file); // read the data serialized from the file + in >> plan; + + return plan; +} + +void Turnstile::planMigration(QString zaddr, QString destAddr) { + // First, get the balance and split up the amounts + auto bal = rpc->getAllBalances()->value(zaddr); + auto splits = splitAmount(bal+2354, 5); + + // Then, generate an intermediate t-Address for each part using getBatchRPC + rpc->getBatchRPC(splits, + [=] (double /*unused*/) { + json payload = { + {"jsonrpc", "1.0"}, + {"id", "someid"}, + {"method", "getnewaddress"}, + }; + return payload; + }, + [=] (QMap* newAddrs) { + // Get block numbers + auto curBlock = Settings::getInstance()->getBlockNumber(); + auto blockNumbers = getBlockNumbers(curBlock, curBlock + 10, splits.size()); + + // Assign the amounts to the addresses. + QList migItems; + + for (int i=0; i < splits.size(); i++) { + auto tAddr = newAddrs->values()[i].get(); + auto item = TurnstileMigrationItem { zaddr, QString::fromStdString(tAddr), destAddr, + blockNumbers[i], splits[i], i == splits.size() -1 }; + migItems.push_back(item); + } + + std::sort(migItems.begin(), migItems.end(), [&] (auto a, auto b) { + return a.blockNumber < b.blockNumber; + }); + + // The first migration is shifted to the current block, so the user sees something + // happening immediately + migItems[0].blockNumber = curBlock; + + writeMigrationPlan(migItems); + auto readPlan = readMigrationPlan(); + + for (auto item : readPlan) { + qDebug() << item.fromAddr << item.intTAddr + << item.destAddr << item.amount << item.blockNumber << item.chaff; + } + } + ); +} + +QList Turnstile::getBlockNumbers(int start, int end, int count) { + QList blocks; + // Generate 'count' numbers between [start, end] + for (int i=0; i < count; i++) { + auto blk = (std::rand() % (end - start)) + start; + blocks.push_back(blk); + } + + return blocks; +} + QList Turnstile::splitAmount(double amount, int parts) { QList amounts; // Need at least 0.0004 ZEC for this diff --git a/src/turnstile.h b/src/turnstile.h index 7a4bac7..427634b 100644 --- a/src/turnstile.h +++ b/src/turnstile.h @@ -1,16 +1,37 @@ #ifndef TURNSTILE_H #define TURNSTILE_H + #include "precompiled.h" +class RPC; + +struct TurnstileMigrationItem { + QString fromAddr; + QString intTAddr; + QString destAddr; + int blockNumber; + double amount; + bool chaff; +}; + class Turnstile { public: - Turnstile(); + Turnstile(RPC* _rpc); ~Turnstile(); + void planMigration(QString zaddr, QString destAddr); QList splitAmount(double amount, int parts); void fillAmounts(QList& amounts, double amount, int count); + + void writeMigrationPlan(QList plan); + QList readMigrationPlan(); + +private: + QList getBlockNumbers(int start, int end, int count); + QString writeableFile(); + RPC* rpc; }; #endif \ No newline at end of file From e6796c904b66b9420b772635727738c547359b77 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Thu, 25 Oct 2018 12:22:25 -0700 Subject: [PATCH 18/25] bugfix, add status --- src/turnstile.cpp | 15 +++++++++------ src/turnstile.h | 9 +++++++++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/turnstile.cpp b/src/turnstile.cpp index 9385ba8..1a8dc02 100644 --- a/src/turnstile.cpp +++ b/src/turnstile.cpp @@ -30,21 +30,22 @@ QString Turnstile::writeableFile() { // Data stream write/read methods for migration items QDataStream &operator<<(QDataStream& ds, const TurnstileMigrationItem& item) { - return ds << "v1" << item.fromAddr << item.intTAddr - << item.destAddr << item.amount << item.blockNumber << item.chaff; + return ds << QString("v1") << item.fromAddr << item.intTAddr + << item.destAddr << item.amount << item.blockNumber << item.chaff << item.status; } QDataStream &operator>>(QDataStream& ds, TurnstileMigrationItem& item) { QString version; return ds >> version >> item.fromAddr >> item.intTAddr - >> item.destAddr >> item.amount >> item.blockNumber >> item.chaff; + >> item.destAddr >> item.amount >> item.blockNumber >> item.chaff >> item.status; } void Turnstile::writeMigrationPlan(QList plan) { QFile file(writeableFile()); - file.open(QIODevice::WriteOnly); + file.open(QIODevice::ReadWrite | QIODevice::Truncate); QDataStream out(&file); // we will serialize the data into the file out << plan; + file.close(); } QList Turnstile::readMigrationPlan() { @@ -57,6 +58,7 @@ QList Turnstile::readMigrationPlan() { QDataStream in(&file); // read the data serialized from the file in >> plan; + file.close(); return plan; } @@ -86,7 +88,8 @@ void Turnstile::planMigration(QString zaddr, QString destAddr) { for (int i=0; i < splits.size(); i++) { auto tAddr = newAddrs->values()[i].get(); auto item = TurnstileMigrationItem { zaddr, QString::fromStdString(tAddr), destAddr, - blockNumbers[i], splits[i], i == splits.size() -1 }; + blockNumbers[i], splits[i], i == splits.size() -1, + TurnstileMigrationItemStatus::NotStarted }; migItems.push_back(item); } @@ -103,7 +106,7 @@ void Turnstile::planMigration(QString zaddr, QString destAddr) { for (auto item : readPlan) { qDebug() << item.fromAddr << item.intTAddr - << item.destAddr << item.amount << item.blockNumber << item.chaff; + << item.destAddr << item.amount << item.blockNumber << item.chaff << item.status; } } ); diff --git a/src/turnstile.h b/src/turnstile.h index 427634b..5acf2ff 100644 --- a/src/turnstile.h +++ b/src/turnstile.h @@ -13,6 +13,15 @@ struct TurnstileMigrationItem { int blockNumber; double amount; bool chaff; + int status; +}; + +enum TurnstileMigrationItemStatus { + NotStarted = 0, + SentToT, + SentToZS, + NotEnoughBalance, + UnknownError }; class Turnstile From 085694a3701e7798af716b0f63387a16b1ebafa4 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Thu, 25 Oct 2018 13:35:49 -0700 Subject: [PATCH 19/25] Execute migration steps --- src/mainwindow.h | 1 - src/precompiled.h | 1 + src/rpc.cpp | 34 ++++++++++++- src/rpc.h | 1 + src/sendtab.cpp | 28 +---------- src/turnstile.cpp | 123 +++++++++++++++++++++++++++++++++++++++++++--- src/turnstile.h | 15 ++++-- src/utils.cpp | 6 ++- src/utils.h | 1 + 9 files changed, 167 insertions(+), 43 deletions(-) diff --git a/src/mainwindow.h b/src/mainwindow.h index 9ef337c..6bb90a6 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -56,7 +56,6 @@ private: Tx createTxFromSendPage(); bool confirmTx(Tx tx, ToFields devFee); - void fillTxJsonParams(json& params, Tx tx); void cancelButton(); void sendButton(); diff --git a/src/precompiled.h b/src/precompiled.h index 552226d..8c6b605 100644 --- a/src/precompiled.h +++ b/src/precompiled.h @@ -2,6 +2,7 @@ /* Add C++ includes here */ #include +#include #include #include #include diff --git a/src/rpc.cpp b/src/rpc.cpp index c70a6f1..cbd6d91 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -286,6 +286,33 @@ void RPC::handleTxError(const QString& error) { msg.exec(); } + +// Build the RPC JSON Parameters for this tx (with the dev fee included if applicable) +void RPC::fillTxJsonParams(json& params, Tx tx) { + Q_ASSERT(params.is_array()); + // Get all the addresses and amounts + json allRecepients = json::array(); + + // For each addr/amt/memo, construct the JSON and also build the confirm dialog box + for (int i=0; i < tx.toAddrs.size(); i++) { + auto toAddr = tx.toAddrs[i]; + + // Construct the JSON params + json rec = json::object(); + rec["address"] = toAddr.addr.toStdString(); + rec["amount"] = toAddr.amount; + if (toAddr.addr.startsWith("z") && !toAddr.encodedMemo.trimmed().isEmpty()) + rec["memo"] = toAddr.encodedMemo.toStdString(); + + allRecepients.push_back(rec); + } + + // Add sender + params.push_back(tx.fromAddr.toStdString()); + params.push_back(allRecepients); +} + + // Refresh received z txs by calling z_listreceivedbyaddress/gettransaction void RPC::refreshReceivedZTrans(QList zaddrs) { @@ -296,7 +323,6 @@ void RPC::refreshReceivedZTrans(QList zaddrs) { return; } - // This method is complicated because z_listreceivedbyaddress only returns the txid, and // we have to make a follow up call to gettransaction to get details of that transaction. // Additionally, it has to be done in batches, because there are multiple z-Addresses, @@ -464,7 +490,11 @@ void RPC::updateUI(bool anyUnconfirmed) { // Temp Turnstile t(this); - t.planMigration(zaddresses->at(1), zaddresses->at(0)); + // t.planMigration( + // "ztsKtGwc7JTEHxQq1xiRWyU9o1sheA3tYjcaFTBfVtp4RKJ782U6pH9STEYUoWQiGn1epfRMmFhkWCUyCSCqByNj9HKnzKU", + // "ztbGDqgkmXQjheivgeirwEvJLD4SUNqsWCGwxwVg4YpGz1ARR8P2rXaptkT14z3NDKamcxNmQuvmvktyokMs7HkutRNSx1D" + // ); + t.executeMigrationStep(); ui->unconfirmedWarning->setVisible(anyUnconfirmed); diff --git a/src/rpc.h b/src/rpc.h index 1bbd6fd..9972816 100644 --- a/src/rpc.h +++ b/src/rpc.h @@ -32,6 +32,7 @@ public: void refreshAddresses(); // Refresh wallet Z-addrs void refreshZECPrice(); + void fillTxJsonParams(json& params, Tx tx); void sendZTransaction (json params, const std::function& cb); void watchTxStatus(); void addNewTxToWatch(Tx tx, const QString& newOpid); diff --git a/src/sendtab.cpp b/src/sendtab.cpp index 5a3c623..fc1c502 100644 --- a/src/sendtab.cpp +++ b/src/sendtab.cpp @@ -7,8 +7,6 @@ #include "precompiled.h" -#include -#include using json = nlohmann::json; void MainWindow::setupSendTab() { @@ -461,30 +459,6 @@ bool MainWindow::confirmTx(Tx tx, ToFields devFee) { } } -// Build the RPC JSON Parameters for this tx (with the dev fee included if applicable) -void MainWindow::fillTxJsonParams(json& params, Tx tx) { - // Get all the addresses and amounts - json allRecepients = json::array(); - - // For each addr/amt/memo, construct the JSON and also build the confirm dialog box - for (int i=0; i < tx.toAddrs.size(); i++) { - auto toAddr = tx.toAddrs[i]; - - // Construct the JSON params - json rec = json::object(); - rec["address"] = toAddr.addr.toStdString(); - rec["amount"] = toAddr.amount; - if (toAddr.addr.startsWith("z") && !toAddr.encodedMemo.trimmed().isEmpty()) - rec["memo"] = toAddr.encodedMemo.toStdString(); - - allRecepients.push_back(rec); - } - - // Add sender - params.push_back(tx.fromAddr.toStdString()); - params.push_back(allRecepients); -} - // Send button clicked void MainWindow::sendButton() { Tx tx = createTxFromSendPage(); @@ -509,7 +483,7 @@ void MainWindow::sendButton() { tx.toAddrs.push_back(devFee); json params = json::array(); - fillTxJsonParams(params, tx); + rpc->fillTxJsonParams(params, tx); std::cout << std::setw(2) << params << std::endl; // And send the Tx diff --git a/src/turnstile.cpp b/src/turnstile.cpp index 1a8dc02..82ea092 100644 --- a/src/turnstile.cpp +++ b/src/turnstile.cpp @@ -1,4 +1,5 @@ #include "turnstile.h" +#include "mainwindow.h" #include "rpc.h" #include "utils.h" #include "settings.h" @@ -14,6 +15,13 @@ Turnstile::Turnstile(RPC* _rpc) { Turnstile::~Turnstile() { } +void printPlan(QList plan) { + for (auto item : plan) { + qDebug() << item.fromAddr << item.intTAddr + << item.destAddr << item.amount << item.blockNumber << item.chaff << item.status; + } +} + QString Turnstile::writeableFile() { auto filename = QStringLiteral("turnstilemigrationplan.dat"); @@ -41,6 +49,9 @@ QDataStream &operator>>(QDataStream& ds, TurnstileMigrationItem& item) { } void Turnstile::writeMigrationPlan(QList plan) { + qDebug() << QString("Writing plan"); + printPlan(plan); + QFile file(writeableFile()); file.open(QIODevice::ReadWrite | QIODevice::Truncate); QDataStream out(&file); // we will serialize the data into the file @@ -59,13 +70,19 @@ QList Turnstile::readMigrationPlan() { in >> plan; file.close(); + + // Sort to see when the next step is. + std::sort(plan.begin(), plan.end(), [&] (auto a, auto b) { + return a.blockNumber < b.blockNumber; + }); + return plan; } void Turnstile::planMigration(QString zaddr, QString destAddr) { // First, get the balance and split up the amounts auto bal = rpc->getAllBalances()->value(zaddr); - auto splits = splitAmount(bal+2354, 5); + auto splits = splitAmount(bal, 5); // Then, generate an intermediate t-Address for each part using getBatchRPC rpc->getBatchRPC(splits, @@ -80,7 +97,7 @@ void Turnstile::planMigration(QString zaddr, QString destAddr) { [=] (QMap* newAddrs) { // Get block numbers auto curBlock = Settings::getInstance()->getBlockNumber(); - auto blockNumbers = getBlockNumbers(curBlock, curBlock + 10, splits.size()); + auto blockNumbers = getBlockNumbers(curBlock, curBlock + 3, splits.size()); // Assign the amounts to the addresses. QList migItems; @@ -103,15 +120,11 @@ void Turnstile::planMigration(QString zaddr, QString destAddr) { writeMigrationPlan(migItems); auto readPlan = readMigrationPlan(); - - for (auto item : readPlan) { - qDebug() << item.fromAddr << item.intTAddr - << item.destAddr << item.amount << item.blockNumber << item.chaff << item.status; - } } ); } + QList Turnstile::getBlockNumbers(int start, int end, int count) { QList blocks; // Generate 'count' numbers between [start, end] @@ -179,4 +192,100 @@ void Turnstile::fillAmounts(QList& amounts, double amount, int count) { amounts.push_back(curAmount); fillAmounts(amounts, amount - curAmount, count - 1); +} + +void Turnstile::executeMigrationStep() { + auto plan = readMigrationPlan(); + + qDebug() << QString("Executing step"); + printPlan(plan); + + // Get to the next unexecuted step + auto eligibleItem = [&] (auto item) { + return !item.chaff && + (item.status == TurnstileMigrationItemStatus::NotStarted || + item.status == TurnstileMigrationItemStatus::SentToT); + }; + auto nextStep = std::find_if(plan.begin(), plan.end(), eligibleItem); + + if (nextStep == plan.end()) return; // Nothing to do + qDebug() << nextStep->blockNumber << ":" << Settings::getInstance()->getBlockNumber(); + if (nextStep->blockNumber > Settings::getInstance()->getBlockNumber()) return; + + // Is this the last step for this address? + auto lastStep = std::find_if(std::next(nextStep), plan.end(), [&] (auto item) { + return item.fromAddr == nextStep->fromAddr && eligibleItem(item); + }) == plan.end(); + + // Execute this step + if (nextStep->status == TurnstileMigrationItemStatus::NotStarted) { + // Does this z addr have enough balance? + auto balance = rpc->getAllBalances()->value(nextStep->fromAddr); + if (nextStep->amount > balance) { + qDebug() << "Not enough balance!"; + nextStep->status = TurnstileMigrationItemStatus::NotEnoughBalance; + writeMigrationPlan(plan); + return; + } + + QList to = { ToFields{ nextStep->intTAddr, nextStep->amount, "", "" } }; + + // If this is the last step, then add chaff and the dev fee to the tx + if (lastStep) { + auto remainingAmount = balance - nextStep->amount; + if (remainingAmount > 0) { + auto devFee = ToFields{ Utils::getDevSproutAddr(), remainingAmount, "", "" }; + to.push_back(devFee); + } + } + + // Create the Tx + auto tx = Tx{ nextStep->fromAddr, to, Utils::getMinerFee() }; + + // And send it + doSendTx(tx, [=] () { + // Update status and write plan to disk + nextStep->status = TurnstileMigrationItemStatus::SentToT; + writeMigrationPlan(plan); + }); + + } else if (nextStep->status == TurnstileMigrationItemStatus::SentToT) { + // Send it to the final destination address. + auto bal = rpc->getAllBalances()->value(nextStep->intTAddr); + auto sendAmt = bal - Utils::getMinerFee(); + + if (sendAmt < 0) { + qDebug() << "Not enough balance!"; + nextStep->status = TurnstileMigrationItemStatus::NotEnoughBalance; + writeMigrationPlan(plan); + return; + } + + QList to = { ToFields{ nextStep->destAddr, sendAmt, "", "" } }; + // Create the Tx + auto tx = Tx{ nextStep->intTAddr, to, Utils::getMinerFee() }; + + // And send it + doSendTx(tx, [=] () { + // Update status and write plan to disk + nextStep->status = TurnstileMigrationItemStatus::SentToZS; + writeMigrationPlan(plan); + }); + } +} + +void Turnstile::doSendTx(Tx tx, std::function cb) { + json params = json::array(); + rpc->fillTxJsonParams(params, tx); + std::cout << std::setw(2) << params << std::endl; + rpc->sendZTransaction(params, [=] (const json& reply) { + QString opid = QString::fromStdString(reply.get()); + qDebug() << opid; + //ui->statusBar->showMessage("Computing Tx: " % opid); + + // And then start monitoring the transaction + rpc->addNewTxToWatch(tx, opid); + + cb(); + }); } \ No newline at end of file diff --git a/src/turnstile.h b/src/turnstile.h index 5acf2ff..b716c39 100644 --- a/src/turnstile.h +++ b/src/turnstile.h @@ -1,10 +1,10 @@ #ifndef TURNSTILE_H #define TURNSTILE_H - #include "precompiled.h" class RPC; +struct Tx; struct TurnstileMigrationItem { QString fromAddr; @@ -30,16 +30,21 @@ public: Turnstile(RPC* _rpc); ~Turnstile(); - void planMigration(QString zaddr, QString destAddr); - QList splitAmount(double amount, int parts); - void fillAmounts(QList& amounts, double amount, int count); + void planMigration(QString zaddr, QString destAddr); + QList splitAmount(double amount, int parts); + void fillAmounts(QList& amounts, double amount, int count); - void writeMigrationPlan(QList plan); QList readMigrationPlan(); + void writeMigrationPlan(QList plan); + + void executeMigrationStep(); private: QList getBlockNumbers(int start, int end, int count); QString writeableFile(); + + void doSendTx(Tx tx, std::function cb); + RPC* rpc; }; diff --git a/src/utils.cpp b/src/utils.cpp index 45ec617..a6dd3c0 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -19,13 +19,17 @@ const QString Utils::getDonationAddr() { return "t1KfJJrSuVYmnNLrw7EZHRv1kZY3zdGGLyb"; } +const QString Utils::getDevSproutAddr() { + return "ztbGDqgkmXQjheivgeirwEvJLD4SUNqsWCGwxwVg4YpGz1ARR8P2rXaptkT14z3NDKamcxNmQuvmvktyokMs7HkutRNSx1D"; +} + // Get the dev fee address based on the transaction const QString Utils::getDevAddr(Tx tx) { auto testnetAddrLookup = [=] (const QString& addr) -> QString { if (addr.startsWith("ztestsapling")) { return "ztestsapling1kdp74adyfsmm9838jaupgfyx3npgw8ut63stjjx757pc248cuc0ymzphqeux60c64qe5qt68ygh"; } else if (addr.startsWith("zt")) { - return "ztbGDqgkmXQjheivgeirwEvJLD4SUNqsWCGwxwVg4YpGz1ARR8P2rXaptkT14z3NDKamcxNmQuvmvktyokMs7HkutRNSx1D"; + return getDevSproutAddr(); } else { return QString(); } diff --git a/src/utils.h b/src/utils.h index 5964e75..8244fcf 100644 --- a/src/utils.h +++ b/src/utils.h @@ -12,6 +12,7 @@ public: static const QString txidStatusMessage; static const QString getTokenName(); + static const QString getDevSproutAddr(); static const QString getDevAddr(Tx tx); static const QString getDonationAddr(); From aca42926a9a728622c5e9700968629e50be63053 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Thu, 25 Oct 2018 13:58:12 -0700 Subject: [PATCH 20/25] ui updates --- .gitignore | 1 + src/mainwindow.cpp | 106 +++++++++++++++++++++++++++++++-------------- src/mainwindow.h | 1 + src/rpc.cpp | 9 ---- src/settings.cpp | 8 ++++ src/settings.h | 2 + src/turnstile.ui | 27 +++++++----- src/ui_turnstile.h | 27 +++++++----- 8 files changed, 120 insertions(+), 61 deletions(-) diff --git a/.gitignore b/.gitignore index dcaf0f6..2747031 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ src/precompiled.h.cpp .qmake.stash zec-qt-wallet zec-qt-wallet.vcxproj* +zec-qt-wallet.pro.user Makefile Makefile.* qrc_application.cpp diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 9816d6a..7a8a9f9 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -26,38 +26,6 @@ MainWindow::MainWindow(QWidget *parent) : // Settings editor setupSettingsModal(); - // Turnstile migration - QObject::connect(ui->actionTurnstile_Migration, &QAction::triggered, [=] () { - Ui_Turnstile turnstile; - QDialog d(this); - turnstile.setupUi(&d); - - QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); - turnstile.msgIcon->setPixmap(icon.pixmap(64, 64)); - - turnstile.migrateZaddList->addItem("All Sprout z-Addrs"); - turnstile.migrateTo->addItem("zs1gv64eu0v2wx7raxqxlmj354y9ycznwaau9kduljzczxztvs4qcl00kn2sjxtejvrxnkucw5xx9u"); - turnstile.privLevel->addItem("Good - 3 tx over 3 days"); - turnstile.privLevel->addItem("Excellent - 5 tx over 5 days"); - turnstile.privLevel->addItem("Paranoid - 10 tx over 7 days"); - - turnstile.buttonBox->button(QDialogButtonBox::Ok)->setText("Start"); - - d.exec(); - }); - - QObject::connect(ui->actionProgress, &QAction::triggered, [=] () { - Ui_TurnstileProgress progress; - QDialog d(this); - progress.setupUi(&d); - - QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning); - progress.msgIcon->setPixmap(icon.pixmap(64, 64)); - - progress.buttonBox->button(QDialogButtonBox::Cancel)->setText("Abort"); - d.exec(); - }); - // Set up exit action QObject::connect(ui->actionExit, &QAction::triggered, this, &MainWindow::close); @@ -90,6 +58,7 @@ MainWindow::MainWindow(QWidget *parent) : setupTransactionsTab(); setupRecieveTab(); setupBalancesTab(); + setupTurnstileDialog(); rpc = new RPC(new QNetworkAccessManager(this), this); rpc->refreshZECPrice(); @@ -97,6 +66,79 @@ MainWindow::MainWindow(QWidget *parent) : rpc->refresh(); } +void MainWindow::setupTurnstileDialog() { + //Turnstile t(this); + // t.planMigration( + // "ztsKtGwc7JTEHxQq1xiRWyU9o1sheA3tYjcaFTBfVtp4RKJ782U6pH9STEYUoWQiGn1epfRMmFhkWCUyCSCqByNj9HKnzKU", + // "ztbGDqgkmXQjheivgeirwEvJLD4SUNqsWCGwxwVg4YpGz1ARR8P2rXaptkT14z3NDKamcxNmQuvmvktyokMs7HkutRNSx1D" + // ); + //t.executeMigrationStep(); + + // Turnstile migration + QObject::connect(ui->actionTurnstile_Migration, &QAction::triggered, [=] () { + Ui_Turnstile turnstile; + QDialog d(this); + turnstile.setupUi(&d); + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); + turnstile.msgIcon->setPixmap(icon.pixmap(64, 64)); + + auto getAllSproutBalance = [=] () { + double bal = 0; + for (auto addr : *rpc->getAllZAddresses()) { + if (Settings::getInstance()->isSproutAddress(addr)) { + bal += rpc->getAllBalances()->value(addr); + } + } + + return bal; + }; + + turnstile.migrateZaddList->addItem("All Sprout z-Addrs"); + turnstile.fromBalance->setText(Settings::getInstance()->getZECUSDDisplayFormat(getAllSproutBalance())); + for (auto addr : *rpc->getAllZAddresses()) { + if (Settings::getInstance()->isSaplingAddress(addr)) { + turnstile.migrateTo->addItem(addr); + } else { + turnstile.migrateZaddList->addItem(addr); + } + } + + QObject::connect(turnstile.migrateZaddList, &QComboBox::currentTextChanged, [=] (auto addr) { + double bal = 0; + if (addr.startsWith("All")) { + bal = getAllSproutBalance(); + } else { + bal = rpc->getAllBalances()->value(addr); + } + + turnstile.fromBalance->setText(Settings::getInstance()->getZECUSDDisplayFormat(bal)); + }); + + turnstile.privLevel->addItem("Good - 3 tx over 3 days"); + turnstile.privLevel->addItem("Excellent - 5 tx over 5 days"); + turnstile.privLevel->addItem("Paranoid - 10 tx over 7 days"); + + turnstile.buttonBox->button(QDialogButtonBox::Ok)->setText("Start"); + + d.exec(); + }); + + + + QObject::connect(ui->actionProgress, &QAction::triggered, [=] () { + Ui_TurnstileProgress progress; + QDialog d(this); + progress.setupUi(&d); + + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning); + progress.msgIcon->setPixmap(icon.pixmap(64, 64)); + + progress.buttonBox->button(QDialogButtonBox::Cancel)->setText("Abort"); + d.exec(); + }); +} + void MainWindow::setupStatusBar() { // Status Bar loadingLabel = new QLabel(); diff --git a/src/mainwindow.h b/src/mainwindow.h index 6bb90a6..df17e82 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -48,6 +48,7 @@ private: void setupRecieveTab(); void setupBalancesTab(); + void setupTurnstileDialog(); void setupSettingsModal(); void setupStatusBar(); diff --git a/src/rpc.cpp b/src/rpc.cpp index cbd6d91..f3174ea 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -487,15 +487,6 @@ void RPC::refreshAddresses() { // Function to create the data model and update the views, used below. void RPC::updateUI(bool anyUnconfirmed) { - - // Temp - Turnstile t(this); - // t.planMigration( - // "ztsKtGwc7JTEHxQq1xiRWyU9o1sheA3tYjcaFTBfVtp4RKJ782U6pH9STEYUoWQiGn1epfRMmFhkWCUyCSCqByNj9HKnzKU", - // "ztbGDqgkmXQjheivgeirwEvJLD4SUNqsWCGwxwVg4YpGz1ARR8P2rXaptkT14z3NDKamcxNmQuvmvktyokMs7HkutRNSx1D" - // ); - t.executeMigrationStep(); - ui->unconfirmedWarning->setVisible(anyUnconfirmed); // Update balances model data, which will update the table too diff --git a/src/settings.cpp b/src/settings.cpp index 637b892..c7fd3a2 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -166,6 +166,14 @@ bool Settings::isSaplingAddress(QString addr) { (!isTestnet() && addr.startsWith("zs")); } +bool Settings::isSproutAddress(QString addr) { + return isZAddress(addr) && !isSaplingAddress(addr); +} + +bool Settings::isZAddress(QString addr) { + return addr.startsWith("z"); +} + bool Settings::isSyncing() { return _isSyncing; } diff --git a/src/settings.h b/src/settings.h index 5142f9d..0c08dc2 100644 --- a/src/settings.h +++ b/src/settings.h @@ -29,6 +29,8 @@ public: void setTestnet(bool isTestnet); bool isSaplingAddress(QString addr); + bool isSproutAddress(QString addr); + bool isZAddress(QString addr); bool isSyncing(); void setSyncing(bool syncing); diff --git a/src/turnstile.ui b/src/turnstile.ui index a12af05..68d9393 100644 --- a/src/turnstile.ui +++ b/src/turnstile.ui @@ -32,7 +32,7 @@ - + Total Fees @@ -42,14 +42,14 @@ - + Privacy Level - + @@ -75,7 +75,7 @@ - + @@ -88,7 +88,7 @@ - + Qt::Vertical @@ -101,14 +101,14 @@ - + 0.0004 ZEC $0.04 - + 0.0004 ZEC $0.04 @@ -131,7 +131,7 @@ - + @@ -151,7 +151,7 @@ - + @@ -164,7 +164,7 @@ - + @@ -174,6 +174,13 @@ + + + + Balance + + + diff --git a/src/ui_turnstile.h b/src/ui_turnstile.h index 8eb3566..6be4eed 100644 --- a/src/ui_turnstile.h +++ b/src/ui_turnstile.h @@ -45,6 +45,7 @@ public: QLabel *label_9; QComboBox *migrateTo; QFrame *line; + QLabel *fromBalance; QDialogButtonBox *buttonBox; void setupUi(QDialog *Turnstile) @@ -70,12 +71,12 @@ public: label_3->setObjectName(QStringLiteral("label_3")); label_3->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop); - gridLayout->addWidget(label_3, 5, 0, 2, 1); + gridLayout->addWidget(label_3, 6, 0, 2, 1); label_2 = new QLabel(groupBox); label_2->setObjectName(QStringLiteral("label_2")); - gridLayout->addWidget(label_2, 4, 0, 1, 1); + gridLayout->addWidget(label_2, 5, 0, 1, 1); label_4 = new QLabel(groupBox); label_4->setObjectName(QStringLiteral("label_4")); @@ -85,7 +86,7 @@ public: sizePolicy.setHeightForWidth(label_4->sizePolicy().hasHeightForWidth()); label_4->setSizePolicy(sizePolicy); - gridLayout->addWidget(label_4, 5, 1, 1, 1); + gridLayout->addWidget(label_4, 6, 1, 1, 1); label = new QLabel(groupBox); label->setObjectName(QStringLiteral("label")); @@ -102,21 +103,21 @@ public: sizePolicy.setHeightForWidth(label_5->sizePolicy().hasHeightForWidth()); label_5->setSizePolicy(sizePolicy); - gridLayout->addWidget(label_5, 6, 1, 1, 1); + gridLayout->addWidget(label_5, 7, 1, 1, 1); verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); - gridLayout->addItem(verticalSpacer, 7, 0, 1, 2); + gridLayout->addItem(verticalSpacer, 8, 0, 1, 2); label_6 = new QLabel(groupBox); label_6->setObjectName(QStringLiteral("label_6")); - gridLayout->addWidget(label_6, 5, 2, 1, 1); + gridLayout->addWidget(label_6, 6, 2, 1, 1); label_7 = new QLabel(groupBox); label_7->setObjectName(QStringLiteral("label_7")); - gridLayout->addWidget(label_7, 6, 2, 1, 1); + gridLayout->addWidget(label_7, 7, 2, 1, 1); migrateZaddList = new QComboBox(groupBox); migrateZaddList->setObjectName(QStringLiteral("migrateZaddList")); @@ -134,7 +135,7 @@ public: sizePolicy2.setHeightForWidth(privLevel->sizePolicy().hasHeightForWidth()); privLevel->setSizePolicy(sizePolicy2); - gridLayout->addWidget(privLevel, 4, 1, 1, 2); + gridLayout->addWidget(privLevel, 5, 1, 1, 2); label_8 = new QLabel(groupBox); label_8->setObjectName(QStringLiteral("label_8")); @@ -147,12 +148,12 @@ public: sizePolicy1.setHeightForWidth(label_9->sizePolicy().hasHeightForWidth()); label_9->setSizePolicy(sizePolicy1); - gridLayout->addWidget(label_9, 3, 0, 1, 1); + gridLayout->addWidget(label_9, 4, 0, 1, 1); migrateTo = new QComboBox(groupBox); migrateTo->setObjectName(QStringLiteral("migrateTo")); - gridLayout->addWidget(migrateTo, 3, 1, 1, 2); + gridLayout->addWidget(migrateTo, 4, 1, 1, 2); line = new QFrame(groupBox); line->setObjectName(QStringLiteral("line")); @@ -161,6 +162,11 @@ public: gridLayout->addWidget(line, 1, 0, 1, 3); + fromBalance = new QLabel(groupBox); + fromBalance->setObjectName(QStringLiteral("fromBalance")); + + gridLayout->addWidget(fromBalance, 3, 1, 1, 1); + verticalLayout_2->addLayout(gridLayout); @@ -197,6 +203,7 @@ public: migrateZaddList->setCurrentText(QString()); label_8->setText(QApplication::translate("Turnstile", "

Funds from Sprout z-Addresses (which start with "zc") need to be moved to the upgraded Sapling z-Addresses (which start with "zs"). The funds cannot be moved directly, but need to be sent through intermediate "transparent" addresses in privacy-preserving way.

This migration can be done automatically for you.

", nullptr)); label_9->setText(QApplication::translate("Turnstile", "To", nullptr)); + fromBalance->setText(QApplication::translate("Turnstile", "Balance", nullptr)); } // retranslateUi }; From 89efb8e28a1b548b24937919b32a9ae0e3ecb64e Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Thu, 25 Oct 2018 15:31:09 -0700 Subject: [PATCH 21/25] simple working --- src/mainwindow.cpp | 17 +++++----- src/rpc.cpp | 8 ++++- src/rpc.h | 8 +++-- src/turnstile.cpp | 78 ++++++++++++++++++++++++++-------------------- src/turnstile.h | 1 - 5 files changed, 68 insertions(+), 44 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 7a8a9f9..f0861c5 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -8,6 +8,7 @@ #include "balancestablemodel.h" #include "settings.h" #include "utils.h" +#import "turnstile.h" #include "senttxstore.h" #include "precompiled.h" @@ -83,7 +84,7 @@ void MainWindow::setupTurnstileDialog() { QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); turnstile.msgIcon->setPixmap(icon.pixmap(64, 64)); - auto getAllSproutBalance = [=] () { + auto fnGetAllSproutBalance = [=] () { double bal = 0; for (auto addr : *rpc->getAllZAddresses()) { if (Settings::getInstance()->isSproutAddress(addr)) { @@ -95,19 +96,20 @@ void MainWindow::setupTurnstileDialog() { }; turnstile.migrateZaddList->addItem("All Sprout z-Addrs"); - turnstile.fromBalance->setText(Settings::getInstance()->getZECUSDDisplayFormat(getAllSproutBalance())); + turnstile.fromBalance->setText(Settings::getInstance()->getZECUSDDisplayFormat(fnGetAllSproutBalance())); for (auto addr : *rpc->getAllZAddresses()) { if (Settings::getInstance()->isSaplingAddress(addr)) { turnstile.migrateTo->addItem(addr); } else { - turnstile.migrateZaddList->addItem(addr); + if (rpc->getAllBalances()->value(addr) > 0) + turnstile.migrateZaddList->addItem(addr); } } QObject::connect(turnstile.migrateZaddList, &QComboBox::currentTextChanged, [=] (auto addr) { double bal = 0; if (addr.startsWith("All")) { - bal = getAllSproutBalance(); + bal = fnGetAllSproutBalance(); } else { bal = rpc->getAllBalances()->value(addr); } @@ -121,11 +123,12 @@ void MainWindow::setupTurnstileDialog() { turnstile.buttonBox->button(QDialogButtonBox::Ok)->setText("Start"); - d.exec(); + if (d.exec() == QDialog::Accepted) { + rpc->getTurnstile()->planMigration( + turnstile.migrateZaddList->currentText(), turnstile.migrateTo->currentText()); + } }); - - QObject::connect(ui->actionProgress, &QAction::triggered, [=] () { Ui_TurnstileProgress progress; QDialog d(this); diff --git a/src/rpc.cpp b/src/rpc.cpp index f3174ea..94f21f4 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -11,6 +11,8 @@ RPC::RPC(QNetworkAccessManager* client, MainWindow* main) { this->main = main; this->ui = main->ui; + this->turnstile = new Turnstile(this); + // Setup balances table model balancesTableModel = new BalancesTableModel(main->ui->balancesTable); main->ui->balancesTable->setModel(balancesTableModel); @@ -56,6 +58,7 @@ RPC::~RPC() { delete transactionsTableModel; delete balancesTableModel; + delete turnstile; delete utxos; delete allBalances; @@ -300,7 +303,7 @@ void RPC::fillTxJsonParams(json& params, Tx tx) { // Construct the JSON params json rec = json::object(); rec["address"] = toAddr.addr.toStdString(); - rec["amount"] = toAddr.amount; + rec["amount"] = QString::number(toAddr.amount, 'f', 8).toDouble(); // Force it through string for rounding if (toAddr.addr.startsWith("z") && !toAddr.encodedMemo.trimmed().isEmpty()) rec["memo"] = toAddr.encodedMemo.toStdString(); @@ -487,6 +490,9 @@ void RPC::refreshAddresses() { // Function to create the data model and update the views, used below. void RPC::updateUI(bool anyUnconfirmed) { + // See if the turnstile migration has any steps that need to be done. + turnstile->executeMigrationStep(); + ui->unconfirmedWarning->setVisible(anyUnconfirmed); // Update balances model data, which will update the table too diff --git a/src/rpc.h b/src/rpc.h index 9972816..dd9b3dd 100644 --- a/src/rpc.h +++ b/src/rpc.h @@ -11,6 +11,7 @@ using json = nlohmann::json; +class Turnstile; struct TransactionItem { QString type; @@ -44,8 +45,10 @@ public: void reloadConnectionInfo(); - void newZaddr (bool sapling, const std::function& cb); - void newTaddr (const std::function& cb); + void newZaddr(bool sapling, const std::function& cb); + void newTaddr(const std::function& cb); + + Turnstile* getTurnstile() { return turnstile; } // Batch method. Note: Because of the template, it has to be in the header file. template @@ -139,6 +142,7 @@ private: Ui::MainWindow* ui; MainWindow* main; + Turnstile* turnstile; // Current balance in the UI. If this number updates, then refresh the UI QString currentBalance; diff --git a/src/turnstile.cpp b/src/turnstile.cpp index 82ea092..f649a4f 100644 --- a/src/turnstile.cpp +++ b/src/turnstile.cpp @@ -1,5 +1,6 @@ #include "turnstile.h" #include "mainwindow.h" +#include "unspentoutput.h" #include "rpc.h" #include "utils.h" #include "settings.h" @@ -18,7 +19,7 @@ Turnstile::~Turnstile() { void printPlan(QList plan) { for (auto item : plan) { qDebug() << item.fromAddr << item.intTAddr - << item.destAddr << item.amount << item.blockNumber << item.chaff << item.status; + << item.destAddr << item.amount << item.blockNumber << item.status; } } @@ -39,13 +40,13 @@ QString Turnstile::writeableFile() { // Data stream write/read methods for migration items QDataStream &operator<<(QDataStream& ds, const TurnstileMigrationItem& item) { return ds << QString("v1") << item.fromAddr << item.intTAddr - << item.destAddr << item.amount << item.blockNumber << item.chaff << item.status; + << item.destAddr << item.amount << item.blockNumber << item.status; } QDataStream &operator>>(QDataStream& ds, TurnstileMigrationItem& item) { QString version; return ds >> version >> item.fromAddr >> item.intTAddr - >> item.destAddr >> item.amount >> item.blockNumber >> item.chaff >> item.status; + >> item.destAddr >> item.amount >> item.blockNumber >> item.status; } void Turnstile::writeMigrationPlan(QList plan) { @@ -105,19 +106,19 @@ void Turnstile::planMigration(QString zaddr, QString destAddr) { for (int i=0; i < splits.size(); i++) { auto tAddr = newAddrs->values()[i].get(); auto item = TurnstileMigrationItem { zaddr, QString::fromStdString(tAddr), destAddr, - blockNumbers[i], splits[i], i == splits.size() -1, + blockNumbers[i], splits[i], TurnstileMigrationItemStatus::NotStarted }; migItems.push_back(item); } - std::sort(migItems.begin(), migItems.end(), [&] (auto a, auto b) { - return a.blockNumber < b.blockNumber; - }); - // The first migration is shifted to the current block, so the user sees something // happening immediately migItems[0].blockNumber = curBlock; + std::sort(migItems.begin(), migItems.end(), [&] (auto a, auto b) { + return a.blockNumber < b.blockNumber; + }); + writeMigrationPlan(migItems); auto readPlan = readMigrationPlan(); } @@ -149,6 +150,9 @@ QList Turnstile::splitAmount(double amount, int parts) { for (auto a : amounts) { sumofparts += a; } + + // Add the Tx fees + sumofparts += amounts.size() * Utils::getMinerFee(); Q_ASSERT(sumofparts == amount); return amounts; @@ -163,18 +167,10 @@ void Turnstile::fillAmounts(QList& amounts, double amount, int count) { // Get the rounded value to 4 decimal places (approx $0.01) double actual = std::floor(amount * 10000) / 10000; - // Reduce the Dev Tx fee from the amount - actual = actual - 0.0001; //Utils::getDevFee(); - // Also account for the fees needed to send all these transactions actual = actual - (Utils::getMinerFee() * (amounts.size() + 1)); - // Calculate the chaff. - double chaff = amount - actual; - amounts.push_back(actual); - if (chaff > 0.00000001) // zcash is split down to 8 decimal places - amounts.push_back(chaff); return; } @@ -182,6 +178,7 @@ void Turnstile::fillAmounts(QList& amounts, double amount, int count) { auto curAmount = std::rand() % (int)std::floor(amount); // Try to round it off + // TODO: Do this via log if (curAmount > 1000) { curAmount = std::floor(curAmount / 100) * 100; } else if (curAmount > 100) { @@ -201,21 +198,30 @@ void Turnstile::executeMigrationStep() { printPlan(plan); // Get to the next unexecuted step - auto eligibleItem = [&] (auto item) { - return !item.chaff && - (item.status == TurnstileMigrationItemStatus::NotStarted || - item.status == TurnstileMigrationItemStatus::SentToT); + auto fnIsEligibleItem = [&] (auto item) { + return item.status == TurnstileMigrationItemStatus::NotStarted || + item.status == TurnstileMigrationItemStatus::SentToT; }; - auto nextStep = std::find_if(plan.begin(), plan.end(), eligibleItem); - if (nextStep == plan.end()) return; // Nothing to do - qDebug() << nextStep->blockNumber << ":" << Settings::getInstance()->getBlockNumber(); - if (nextStep->blockNumber > Settings::getInstance()->getBlockNumber()) return; + // Fn to find if there are any unconfirmed funds for this address. + auto fnHasUnconfirmed = [=] (QString addr) { + auto utxoset = rpc->getUTXOs(); + return std::find_if(utxoset->begin(), utxoset->end(), [=] (auto utxo) { + return utxo.address == addr && utxo.confirmations == 0; + }) != utxoset->end(); + }; + + // Find the next step + auto nextStep = std::find_if(plan.begin(), plan.end(), fnIsEligibleItem); + + if (nextStep == plan.end()) + return; // Nothing to do + + if (nextStep->blockNumber > Settings::getInstance()->getBlockNumber()) + return; // Is this the last step for this address? - auto lastStep = std::find_if(std::next(nextStep), plan.end(), [&] (auto item) { - return item.fromAddr == nextStep->fromAddr && eligibleItem(item); - }) == plan.end(); + auto lastStep = std::find_if(std::next(nextStep), plan.end(), fnIsEligibleItem) == plan.end(); // Execute this step if (nextStep->status == TurnstileMigrationItemStatus::NotStarted) { @@ -228,19 +234,18 @@ void Turnstile::executeMigrationStep() { return; } - QList to = { ToFields{ nextStep->intTAddr, nextStep->amount, "", "" } }; + auto to = ToFields{ nextStep->intTAddr, nextStep->amount, "", "" }; - // If this is the last step, then add chaff and the dev fee to the tx + // If this is the last step, then send the remaining amount instead of the actual amount. if (lastStep) { - auto remainingAmount = balance - nextStep->amount; + auto remainingAmount = balance - Utils::getMinerFee(); if (remainingAmount > 0) { - auto devFee = ToFields{ Utils::getDevSproutAddr(), remainingAmount, "", "" }; - to.push_back(devFee); + to.amount = remainingAmount; } } // Create the Tx - auto tx = Tx{ nextStep->fromAddr, to, Utils::getMinerFee() }; + auto tx = Tx{ nextStep->fromAddr, { to }, Utils::getMinerFee() }; // And send it doSendTx(tx, [=] () { @@ -250,6 +255,12 @@ void Turnstile::executeMigrationStep() { }); } else if (nextStep->status == TurnstileMigrationItemStatus::SentToT) { + // First thing to do is check to see if the funds are confirmed. + if (fnHasUnconfirmed(nextStep->intTAddr)) { + qDebug() << QString("unconfirmed, waiting"); + return; + } + // Send it to the final destination address. auto bal = rpc->getAllBalances()->value(nextStep->intTAddr); auto sendAmt = bal - Utils::getMinerFee(); @@ -262,6 +273,7 @@ void Turnstile::executeMigrationStep() { } QList to = { ToFields{ nextStep->destAddr, sendAmt, "", "" } }; + // Create the Tx auto tx = Tx{ nextStep->intTAddr, to, Utils::getMinerFee() }; diff --git a/src/turnstile.h b/src/turnstile.h index b716c39..0a4ff88 100644 --- a/src/turnstile.h +++ b/src/turnstile.h @@ -12,7 +12,6 @@ struct TurnstileMigrationItem { QString destAddr; int blockNumber; double amount; - bool chaff; int status; }; From e8555ea90680a248574f92c6278d844abf878b4d Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Thu, 25 Oct 2018 16:06:56 -0700 Subject: [PATCH 22/25] UI polish --- src/turnstile.cpp | 18 +++++--- src/turnstile.ui | 110 +++++++++++++++++++++----------------------- src/ui_turnstile.h | 112 ++++++++++++++++++++------------------------- 3 files changed, 112 insertions(+), 128 deletions(-) diff --git a/src/turnstile.cpp b/src/turnstile.cpp index f649a4f..4c717b5 100644 --- a/src/turnstile.cpp +++ b/src/turnstile.cpp @@ -144,6 +144,7 @@ QList Turnstile::splitAmount(double amount, int parts) { return amounts; fillAmounts(amounts, amount, parts); + qDebug() << amounts; // Ensure they all add up! double sumofparts = 0; @@ -159,7 +160,7 @@ QList Turnstile::splitAmount(double amount, int parts) { } void Turnstile::fillAmounts(QList& amounts, double amount, int count) { - if (count == 1 || amount < 1) { + if (count == 1 || amount < 0.01) { // Split the chaff. // Chaff is all amounts lesser than 0.0001 ZEC. The chaff will be added to the // dev fee, and is done so to protect privacy. @@ -175,16 +176,19 @@ void Turnstile::fillAmounts(QList& amounts, double amount, int count) { } // Get a random amount off the amount (between half and full) and call recursively. - auto curAmount = std::rand() % (int)std::floor(amount); + // Multiply by hundered, because we'll operate on 0.01 ZEC minimum. We'll divide by 100 later + double curAmount = std::rand() % (int)std::floor(amount * 100); // Try to round it off - // TODO: Do this via log - if (curAmount > 1000) { - curAmount = std::floor(curAmount / 100) * 100; - } else if (curAmount > 100) { - curAmount = std::floor(curAmount / 10) * 10; + auto places = (int)std::floor(std::log10(curAmount)); + if (places > 0) { + auto a = std::pow(10, places); + curAmount = std::floor(curAmount / a) * a; } + // And divide by 100 + curAmount = curAmount / 100; + if (curAmount > 0) amounts.push_back(curAmount); diff --git a/src/turnstile.ui b/src/turnstile.ui index 68d9393..03af43e 100644 --- a/src/turnstile.ui +++ b/src/turnstile.ui @@ -32,33 +32,16 @@
- - - - Total Fees - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - Privacy Level - - - - - - + 0 0 - Miner Fee: + Privacy Level @@ -75,46 +58,6 @@
- - - - - 0 - 0 - - - - Dev Fee: - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - 0.0004 ZEC $0.04 - - - - - - - 0.0004 ZEC $0.04 - - - @@ -181,6 +124,55 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + Miner Fees + + + + + + + + 0 + 0 + + + + 0.0004 ZEC $0.04 + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + Total Balance + + +
diff --git a/src/ui_turnstile.h b/src/ui_turnstile.h index 6be4eed..b787a6a 100644 --- a/src/ui_turnstile.h +++ b/src/ui_turnstile.h @@ -31,14 +31,8 @@ public: QVBoxLayout *verticalLayout_2; QGridLayout *gridLayout; QLabel *msgIcon; - QLabel *label_3; QLabel *label_2; - QLabel *label_4; QLabel *label; - QLabel *label_5; - QSpacerItem *verticalSpacer; - QLabel *label_6; - QLabel *label_7; QComboBox *migrateZaddList; QComboBox *privLevel; QLabel *label_8; @@ -46,6 +40,10 @@ public: QComboBox *migrateTo; QFrame *line; QLabel *fromBalance; + QSpacerItem *verticalSpacer; + QLabel *label_5; + QLabel *label_7; + QLabel *label_3; QDialogButtonBox *buttonBox; void setupUi(QDialog *Turnstile) @@ -67,73 +65,38 @@ public: gridLayout->addWidget(msgIcon, 0, 0, 1, 1); - label_3 = new QLabel(groupBox); - label_3->setObjectName(QStringLiteral("label_3")); - label_3->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop); - - gridLayout->addWidget(label_3, 6, 0, 2, 1); - label_2 = new QLabel(groupBox); label_2->setObjectName(QStringLiteral("label_2")); + QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(label_2->sizePolicy().hasHeightForWidth()); + label_2->setSizePolicy(sizePolicy); gridLayout->addWidget(label_2, 5, 0, 1, 1); - label_4 = new QLabel(groupBox); - label_4->setObjectName(QStringLiteral("label_4")); - QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - sizePolicy.setHorizontalStretch(0); - sizePolicy.setVerticalStretch(0); - sizePolicy.setHeightForWidth(label_4->sizePolicy().hasHeightForWidth()); - label_4->setSizePolicy(sizePolicy); - - gridLayout->addWidget(label_4, 6, 1, 1, 1); - label = new QLabel(groupBox); label->setObjectName(QStringLiteral("label")); - QSizePolicy sizePolicy1(QSizePolicy::Minimum, QSizePolicy::Preferred); - sizePolicy1.setHorizontalStretch(0); - sizePolicy1.setVerticalStretch(0); - sizePolicy1.setHeightForWidth(label->sizePolicy().hasHeightForWidth()); - label->setSizePolicy(sizePolicy1); + sizePolicy.setHeightForWidth(label->sizePolicy().hasHeightForWidth()); + label->setSizePolicy(sizePolicy); gridLayout->addWidget(label, 2, 0, 1, 1); - label_5 = new QLabel(groupBox); - label_5->setObjectName(QStringLiteral("label_5")); - sizePolicy.setHeightForWidth(label_5->sizePolicy().hasHeightForWidth()); - label_5->setSizePolicy(sizePolicy); - - gridLayout->addWidget(label_5, 7, 1, 1, 1); - - verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); - - gridLayout->addItem(verticalSpacer, 8, 0, 1, 2); - - label_6 = new QLabel(groupBox); - label_6->setObjectName(QStringLiteral("label_6")); - - gridLayout->addWidget(label_6, 6, 2, 1, 1); - - label_7 = new QLabel(groupBox); - label_7->setObjectName(QStringLiteral("label_7")); - - gridLayout->addWidget(label_7, 7, 2, 1, 1); - migrateZaddList = new QComboBox(groupBox); migrateZaddList->setObjectName(QStringLiteral("migrateZaddList")); - QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Fixed); - sizePolicy2.setHorizontalStretch(0); - sizePolicy2.setVerticalStretch(0); - sizePolicy2.setHeightForWidth(migrateZaddList->sizePolicy().hasHeightForWidth()); - migrateZaddList->setSizePolicy(sizePolicy2); + QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Fixed); + sizePolicy1.setHorizontalStretch(0); + sizePolicy1.setVerticalStretch(0); + sizePolicy1.setHeightForWidth(migrateZaddList->sizePolicy().hasHeightForWidth()); + migrateZaddList->setSizePolicy(sizePolicy1); migrateZaddList->setEditable(false); gridLayout->addWidget(migrateZaddList, 2, 1, 1, 2); privLevel = new QComboBox(groupBox); privLevel->setObjectName(QStringLiteral("privLevel")); - sizePolicy2.setHeightForWidth(privLevel->sizePolicy().hasHeightForWidth()); - privLevel->setSizePolicy(sizePolicy2); + sizePolicy1.setHeightForWidth(privLevel->sizePolicy().hasHeightForWidth()); + privLevel->setSizePolicy(sizePolicy1); gridLayout->addWidget(privLevel, 5, 1, 1, 2); @@ -145,8 +108,8 @@ public: label_9 = new QLabel(groupBox); label_9->setObjectName(QStringLiteral("label_9")); - sizePolicy1.setHeightForWidth(label_9->sizePolicy().hasHeightForWidth()); - label_9->setSizePolicy(sizePolicy1); + sizePolicy.setHeightForWidth(label_9->sizePolicy().hasHeightForWidth()); + label_9->setSizePolicy(sizePolicy); gridLayout->addWidget(label_9, 4, 0, 1, 1); @@ -167,6 +130,33 @@ public: gridLayout->addWidget(fromBalance, 3, 1, 1, 1); + verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + gridLayout->addItem(verticalSpacer, 7, 0, 2, 3); + + label_5 = new QLabel(groupBox); + label_5->setObjectName(QStringLiteral("label_5")); + sizePolicy.setHeightForWidth(label_5->sizePolicy().hasHeightForWidth()); + label_5->setSizePolicy(sizePolicy); + + gridLayout->addWidget(label_5, 6, 0, 1, 1); + + label_7 = new QLabel(groupBox); + label_7->setObjectName(QStringLiteral("label_7")); + QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Preferred); + sizePolicy2.setHorizontalStretch(0); + sizePolicy2.setVerticalStretch(0); + sizePolicy2.setHeightForWidth(label_7->sizePolicy().hasHeightForWidth()); + label_7->setSizePolicy(sizePolicy2); + label_7->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter); + + gridLayout->addWidget(label_7, 6, 1, 1, 2); + + label_3 = new QLabel(groupBox); + label_3->setObjectName(QStringLiteral("label_3")); + + gridLayout->addWidget(label_3, 3, 0, 1, 1); + verticalLayout_2->addLayout(gridLayout); @@ -193,17 +183,15 @@ public: Turnstile->setWindowTitle(QApplication::translate("Turnstile", "Turnstile Migration", nullptr)); groupBox->setTitle(QApplication::translate("Turnstile", "Turnstile Migration", nullptr)); msgIcon->setText(QString()); - label_3->setText(QApplication::translate("Turnstile", "Total Fees", nullptr)); label_2->setText(QApplication::translate("Turnstile", "Privacy Level", nullptr)); - label_4->setText(QApplication::translate("Turnstile", "Miner Fee:", nullptr)); label->setText(QApplication::translate("Turnstile", "From", nullptr)); - label_5->setText(QApplication::translate("Turnstile", "Dev Fee: ", nullptr)); - label_6->setText(QApplication::translate("Turnstile", "0.0004 ZEC $0.04", nullptr)); - label_7->setText(QApplication::translate("Turnstile", "0.0004 ZEC $0.04", nullptr)); migrateZaddList->setCurrentText(QString()); label_8->setText(QApplication::translate("Turnstile", "

Funds from Sprout z-Addresses (which start with "zc") need to be moved to the upgraded Sapling z-Addresses (which start with "zs"). The funds cannot be moved directly, but need to be sent through intermediate "transparent" addresses in privacy-preserving way.

This migration can be done automatically for you.

", nullptr)); label_9->setText(QApplication::translate("Turnstile", "To", nullptr)); fromBalance->setText(QApplication::translate("Turnstile", "Balance", nullptr)); + label_5->setText(QApplication::translate("Turnstile", "Miner Fees", nullptr)); + label_7->setText(QApplication::translate("Turnstile", "0.0004 ZEC $0.04", nullptr)); + label_3->setText(QApplication::translate("Turnstile", "Total Balance", nullptr)); } // retranslateUi }; From 71abf9228058d35fc2f9e920143b69dfbe222279 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Thu, 25 Oct 2018 22:34:42 -0700 Subject: [PATCH 23/25] small bugfixes --- src/mainwindow.cpp | 66 ++++++++++++++++++++++++++++++++------ src/turnstile.cpp | 47 +++++++++++++++++++++++++-- src/turnstile.h | 13 +++++++- src/turnstile.ui | 2 +- src/turnstileprogress.ui | 4 +-- src/ui_turnstile.h | 16 ++++----- src/ui_turnstileprogress.h | 22 ++++++------- 7 files changed, 134 insertions(+), 36 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f0861c5..b721438 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -68,12 +68,6 @@ MainWindow::MainWindow(QWidget *parent) : } void MainWindow::setupTurnstileDialog() { - //Turnstile t(this); - // t.planMigration( - // "ztsKtGwc7JTEHxQq1xiRWyU9o1sheA3tYjcaFTBfVtp4RKJ782U6pH9STEYUoWQiGn1epfRMmFhkWCUyCSCqByNj9HKnzKU", - // "ztbGDqgkmXQjheivgeirwEvJLD4SUNqsWCGwxwVg4YpGz1ARR8P2rXaptkT14z3NDKamcxNmQuvmvktyokMs7HkutRNSx1D" - // ); - //t.executeMigrationStep(); // Turnstile migration QObject::connect(ui->actionTurnstile_Migration, &QAction::triggered, [=] () { @@ -117,18 +111,39 @@ void MainWindow::setupTurnstileDialog() { turnstile.fromBalance->setText(Settings::getInstance()->getZECUSDDisplayFormat(bal)); }); - turnstile.privLevel->addItem("Good - 3 tx over 3 days"); - turnstile.privLevel->addItem("Excellent - 5 tx over 5 days"); - turnstile.privLevel->addItem("Paranoid - 10 tx over 7 days"); + // Privacy level combobox + // Num tx over num blocks + QList> privOptions; + privOptions.push_back(QPair(3, 3)); + privOptions.push_back(QPair(5, 5)); + privOptions.push_back(QPair(10, 7)); + + QObject::connect(turnstile.privLevel, QOverload::of(&QComboBox::currentIndexChanged), [=] (auto idx) { + // Update the fees + turnstile.minerFee->setText( + Settings::getInstance()->getZECUSDDisplayFormat(privOptions[idx].first * Utils::getMinerFee())); + }); + + turnstile.privLevel->addItem("Good - 3 tx over 3 blocks"); + turnstile.privLevel->addItem("Excellent - 5 tx over 5 blocks"); + turnstile.privLevel->addItem("Paranoid - 10 tx over 7 blocks"); turnstile.buttonBox->button(QDialogButtonBox::Ok)->setText("Start"); if (d.exec() == QDialog::Accepted) { + auto privLevel = privOptions[turnstile.privLevel->currentIndex()]; rpc->getTurnstile()->planMigration( - turnstile.migrateZaddList->currentText(), turnstile.migrateTo->currentText()); + turnstile.migrateZaddList->currentText(), + turnstile.migrateTo->currentText(), + privLevel.first, privLevel.second); + + QMessageBox::information(this, "Backup your wallet.dat", + "The migration will now start. You can check progress in the File -> Turnstile Migration menu.\n\nYOU MUST BACKUP YOUR wallet.dat NOW!.\n\nNew Addresses have been added to your wallet which will be used for the migration.", + QMessageBox::Ok); } }); + // Progress update button QObject::connect(ui->actionProgress, &QAction::triggered, [=] () { Ui_TurnstileProgress progress; QDialog d(this); @@ -138,6 +153,37 @@ void MainWindow::setupTurnstileDialog() { progress.msgIcon->setPixmap(icon.pixmap(64, 64)); progress.buttonBox->button(QDialogButtonBox::Cancel)->setText("Abort"); + + auto fnUpdateProgressUI = [=] () { + // Get the plan progress + if (rpc->getTurnstile()->isMigrationActive()) { + auto curProgress = rpc->getTurnstile()->getPlanProgress(); + + progress.progressTxt->setText(QString::number(curProgress.step) % QString(" / ") % QString::number(curProgress.totalSteps)); + progress.progressBar->setValue(100 * curProgress.step / curProgress.totalSteps); + + auto nextTxBlock = curProgress.nextBlock - Settings::getInstance()->getBlockNumber(); + + if (curProgress.step == curProgress.totalSteps) { + progress.nextTx->setText("Turnstile migration finished"); + } else { + progress.nextTx->setText(QString("Next transaction in ") + % QString::number(nextTxBlock < 0 ? 0 : nextTxBlock) + % " blocks"); + } + + } else { + progress.progressTxt->setText(""); + progress.progressBar->setValue(0); + progress.nextTx->setText("No turnstile migration is in progress"); + } + }; + + QTimer progressTimer(this); + QObject::connect(&progressTimer, &QTimer::timeout, fnUpdateProgressUI); + progressTimer.start(Utils::updateSpeed); + fnUpdateProgressUI(); + d.exec(); }); } diff --git a/src/turnstile.cpp b/src/turnstile.cpp index 4c717b5..c1b278a 100644 --- a/src/turnstile.cpp +++ b/src/turnstile.cpp @@ -80,10 +80,10 @@ QList Turnstile::readMigrationPlan() { return plan; } -void Turnstile::planMigration(QString zaddr, QString destAddr) { +void Turnstile::planMigration(QString zaddr, QString destAddr, int numsplits, int numBlocks) { // First, get the balance and split up the amounts auto bal = rpc->getAllBalances()->value(zaddr); - auto splits = splitAmount(bal, 5); + auto splits = splitAmount(bal, numsplits); // Then, generate an intermediate t-Address for each part using getBatchRPC rpc->getBatchRPC(splits, @@ -98,7 +98,7 @@ void Turnstile::planMigration(QString zaddr, QString destAddr) { [=] (QMap* newAddrs) { // Get block numbers auto curBlock = Settings::getInstance()->getBlockNumber(); - auto blockNumbers = getBlockNumbers(curBlock, curBlock + 3, splits.size()); + auto blockNumbers = getBlockNumbers(curBlock, curBlock + numBlocks, splits.size()); // Assign the amounts to the addresses. QList migItems; @@ -195,6 +195,47 @@ void Turnstile::fillAmounts(QList& amounts, double amount, int count) { fillAmounts(amounts, amount - curAmount, count - 1); } +QList::Iterator +Turnstile::getNextStep(QList& plan) { + // Get to the next unexecuted step + auto fnIsEligibleItem = [&] (auto item) { + return item.status == TurnstileMigrationItemStatus::NotStarted || + item.status == TurnstileMigrationItemStatus::SentToT; + }; + + // // Fn to find if there are any unconfirmed funds for this address. + // auto fnHasUnconfirmed = [=] (QString addr) { + // auto utxoset = rpc->getUTXOs(); + // return std::find_if(utxoset->begin(), utxoset->end(), [=] (auto utxo) { + // return utxo.address == addr && utxo.confirmations == 0; + // }) != utxoset->end(); + // }; + + // Find the next step + auto nextStep = std::find_if(plan.begin(), plan.end(), fnIsEligibleItem); + return nextStep; +} + +bool Turnstile::isMigrationActive() { + auto plan = readMigrationPlan(); + if (plan.isEmpty()) return false; + + return true; +} + +ProgressReport Turnstile::getPlanProgress() { + auto plan = readMigrationPlan(); + + auto nextStep = getNextStep(plan); + + auto step = std::distance(plan.begin(), nextStep); + auto total = plan.size(); + + auto nextBlock = nextStep == plan.end() ? 0 : nextStep->blockNumber; + + return ProgressReport{(int)step*2, total*2, nextBlock}; +} + void Turnstile::executeMigrationStep() { auto plan = readMigrationPlan(); diff --git a/src/turnstile.h b/src/turnstile.h index 0a4ff88..a08e504 100644 --- a/src/turnstile.h +++ b/src/turnstile.h @@ -23,13 +23,19 @@ enum TurnstileMigrationItemStatus { UnknownError }; +struct ProgressReport { + int step; + int totalSteps; + int nextBlock; +}; + class Turnstile { public: Turnstile(RPC* _rpc); ~Turnstile(); - void planMigration(QString zaddr, QString destAddr); + void planMigration(QString zaddr, QString destAddr, int splits, int numBlocks); QList splitAmount(double amount, int parts); void fillAmounts(QList& amounts, double amount, int count); @@ -37,6 +43,8 @@ public: void writeMigrationPlan(QList plan); void executeMigrationStep(); + ProgressReport getPlanProgress(); + bool isMigrationActive(); private: QList getBlockNumbers(int start, int end, int count); @@ -44,6 +52,9 @@ private: void doSendTx(Tx tx, std::function cb); + + QList::Iterator getNextStep(QList& plan); + RPC* rpc; }; diff --git a/src/turnstile.ui b/src/turnstile.ui index 03af43e..acf6e64 100644 --- a/src/turnstile.ui +++ b/src/turnstile.ui @@ -151,7 +151,7 @@
- + 0 diff --git a/src/turnstileprogress.ui b/src/turnstileprogress.ui index 5b09ebd..3c337aa 100644 --- a/src/turnstileprogress.ui +++ b/src/turnstileprogress.ui @@ -45,14 +45,14 @@ - + Next Transaction in 4 hours - + 4 / 12 diff --git a/src/ui_turnstile.h b/src/ui_turnstile.h index b787a6a..fe1d77c 100644 --- a/src/ui_turnstile.h +++ b/src/ui_turnstile.h @@ -42,7 +42,7 @@ public: QLabel *fromBalance; QSpacerItem *verticalSpacer; QLabel *label_5; - QLabel *label_7; + QLabel *minerFee; QLabel *label_3; QDialogButtonBox *buttonBox; @@ -141,16 +141,16 @@ public: gridLayout->addWidget(label_5, 6, 0, 1, 1); - label_7 = new QLabel(groupBox); - label_7->setObjectName(QStringLiteral("label_7")); + minerFee = new QLabel(groupBox); + minerFee->setObjectName(QStringLiteral("minerFee")); QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Preferred); sizePolicy2.setHorizontalStretch(0); sizePolicy2.setVerticalStretch(0); - sizePolicy2.setHeightForWidth(label_7->sizePolicy().hasHeightForWidth()); - label_7->setSizePolicy(sizePolicy2); - label_7->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter); + sizePolicy2.setHeightForWidth(minerFee->sizePolicy().hasHeightForWidth()); + minerFee->setSizePolicy(sizePolicy2); + minerFee->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter); - gridLayout->addWidget(label_7, 6, 1, 1, 2); + gridLayout->addWidget(minerFee, 6, 1, 1, 2); label_3 = new QLabel(groupBox); label_3->setObjectName(QStringLiteral("label_3")); @@ -190,7 +190,7 @@ public: label_9->setText(QApplication::translate("Turnstile", "To", nullptr)); fromBalance->setText(QApplication::translate("Turnstile", "Balance", nullptr)); label_5->setText(QApplication::translate("Turnstile", "Miner Fees", nullptr)); - label_7->setText(QApplication::translate("Turnstile", "0.0004 ZEC $0.04", nullptr)); + minerFee->setText(QApplication::translate("Turnstile", "0.0004 ZEC $0.04", nullptr)); label_3->setText(QApplication::translate("Turnstile", "Total Balance", nullptr)); } // retranslateUi diff --git a/src/ui_turnstileprogress.h b/src/ui_turnstileprogress.h index 2d34909..0f5f48d 100644 --- a/src/ui_turnstileprogress.h +++ b/src/ui_turnstileprogress.h @@ -28,8 +28,8 @@ public: QProgressBar *progressBar; QLabel *label_4; QFrame *line; - QLabel *label; - QLabel *label_3; + QLabel *nextTx; + QLabel *progressTxt; QLabel *label_2; QLabel *msgIcon; QDialogButtonBox *buttonBox; @@ -67,16 +67,16 @@ public: gridLayout->addWidget(line, 4, 0, 1, 3); - label = new QLabel(TurnstileProgress); - label->setObjectName(QStringLiteral("label")); + nextTx = new QLabel(TurnstileProgress); + nextTx->setObjectName(QStringLiteral("nextTx")); - gridLayout->addWidget(label, 5, 0, 1, 3); + gridLayout->addWidget(nextTx, 5, 0, 1, 3); - label_3 = new QLabel(TurnstileProgress); - label_3->setObjectName(QStringLiteral("label_3")); - label_3->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + progressTxt = new QLabel(TurnstileProgress); + progressTxt->setObjectName(QStringLiteral("progressTxt")); + progressTxt->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); - gridLayout->addWidget(label_3, 2, 2, 1, 1); + gridLayout->addWidget(progressTxt, 2, 2, 1, 1); label_2 = new QLabel(TurnstileProgress); label_2->setObjectName(QStringLiteral("label_2")); @@ -124,8 +124,8 @@ public: { TurnstileProgress->setWindowTitle(QApplication::translate("TurnstileProgress", "Dialog", nullptr)); label_4->setText(QApplication::translate("TurnstileProgress", "Please Ensure you have your wallet.dat backed up!", nullptr)); - label->setText(QApplication::translate("TurnstileProgress", "Next Transaction in 4 hours", nullptr)); - label_3->setText(QApplication::translate("TurnstileProgress", "4 / 12", nullptr)); + nextTx->setText(QApplication::translate("TurnstileProgress", "Next Transaction in 4 hours", nullptr)); + progressTxt->setText(QApplication::translate("TurnstileProgress", "4 / 12", nullptr)); label_2->setText(QApplication::translate("TurnstileProgress", "Migration Progress", nullptr)); msgIcon->setText(QApplication::translate("TurnstileProgress", "TextLabel", nullptr)); } // retranslateUi From 719f6d9ce4c1100c7965ce75e25690b56cb6853b Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Thu, 25 Oct 2018 22:45:16 -0700 Subject: [PATCH 24/25] progress error message --- src/mainwindow.cpp | 6 +++++- src/rpc.cpp | 10 +++------- src/turnstile.cpp | 9 +++++++-- src/turnstile.h | 1 + src/unspentoutput.cpp | 8 -------- src/unspentoutput.h | 7 ++----- 6 files changed, 18 insertions(+), 23 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b721438..ba41ba3 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -165,7 +165,11 @@ void MainWindow::setupTurnstileDialog() { auto nextTxBlock = curProgress.nextBlock - Settings::getInstance()->getBlockNumber(); if (curProgress.step == curProgress.totalSteps) { - progress.nextTx->setText("Turnstile migration finished"); + auto txt = QString("Turnstile migration finished"); + if (curProgress.hasErrors) { + txt = txt + ". There were some errors.\n\nYour funds are all in your wallet, so you should be able to finish moving them manually."; + } + progress.nextTx->setText(txt); } else { progress.nextTx->setText(QString("Next transaction in ") % QString::number(nextTxBlock < 0 ? 0 : nextTxBlock) diff --git a/src/rpc.cpp b/src/rpc.cpp index 94f21f4..016a263 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -523,13 +523,9 @@ bool RPC::processUnspent(const json& reply) { } utxos->push_back( - UnspentOutput( - qsAddr, - QString::fromStdString(it["txid"]), - QString::number(it["amount"].get(), 'g', 8), - confirmations - ) - ); + UnspentOutput{ qsAddr, QString::fromStdString(it["txid"]), + QString::number(it["amount"].get(), 'g', 8), + (int)confirmations, it["spendable"].get() }); (*allBalances)[qsAddr] = (*allBalances)[qsAddr] + it["amount"].get(); } diff --git a/src/turnstile.cpp b/src/turnstile.cpp index c1b278a..b9cede9 100644 --- a/src/turnstile.cpp +++ b/src/turnstile.cpp @@ -233,7 +233,12 @@ ProgressReport Turnstile::getPlanProgress() { auto nextBlock = nextStep == plan.end() ? 0 : nextStep->blockNumber; - return ProgressReport{(int)step*2, total*2, nextBlock}; + bool hasErrors = std::find_if(plan.begin(), plan.end(), [=] (auto i) { + return i.status == TurnstileMigrationItemStatus::NotEnoughBalance || + i.status == TurnstileMigrationItemStatus::UnknownError; + }) != plan.end(); + + return ProgressReport{(int)step*2, total*2, nextBlock, hasErrors}; } void Turnstile::executeMigrationStep() { @@ -252,7 +257,7 @@ void Turnstile::executeMigrationStep() { auto fnHasUnconfirmed = [=] (QString addr) { auto utxoset = rpc->getUTXOs(); return std::find_if(utxoset->begin(), utxoset->end(), [=] (auto utxo) { - return utxo.address == addr && utxo.confirmations == 0; + return utxo.address == addr && utxo.confirmations == 0 && utxo.spendable; }) != utxoset->end(); }; diff --git a/src/turnstile.h b/src/turnstile.h index a08e504..7b421a8 100644 --- a/src/turnstile.h +++ b/src/turnstile.h @@ -27,6 +27,7 @@ struct ProgressReport { int step; int totalSteps; int nextBlock; + bool hasErrors; }; class Turnstile diff --git a/src/unspentoutput.cpp b/src/unspentoutput.cpp index 67068f3..7b3a2d6 100644 --- a/src/unspentoutput.cpp +++ b/src/unspentoutput.cpp @@ -1,9 +1 @@ #include "unspentoutput.h" - -UnspentOutput::UnspentOutput(QString address, QString txid, QString amount, int confirmations) -{ - this->address = address; - this->txid = txid; - this->amount = amount; - this->confirmations = confirmations; -} diff --git a/src/unspentoutput.h b/src/unspentoutput.h index d6af3b1..e106e5d 100644 --- a/src/unspentoutput.h +++ b/src/unspentoutput.h @@ -3,15 +3,12 @@ #include "precompiled.h" -class UnspentOutput -{ -public: - UnspentOutput(QString address, QString txid, QString amount, int confirmations); - +struct UnspentOutput { QString address; QString txid; QString amount; int confirmations; + bool spendable; }; From ae00476b62818219bc69e6f86d9d18aea0bb6323 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Thu, 25 Oct 2018 23:05:45 -0700 Subject: [PATCH 25/25] bug fixes --- src/turnstile.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/turnstile.cpp b/src/turnstile.cpp index b9cede9..d7d810e 100644 --- a/src/turnstile.cpp +++ b/src/turnstile.cpp @@ -155,7 +155,7 @@ QList Turnstile::splitAmount(double amount, int parts) { // Add the Tx fees sumofparts += amounts.size() * Utils::getMinerFee(); - Q_ASSERT(sumofparts == amount); + Q_ASSERT(QString::number(sumofparts, 'f', 8) == QString::number(amount, 'f', 8)); return amounts; } @@ -276,6 +276,11 @@ void Turnstile::executeMigrationStep() { // Execute this step if (nextStep->status == TurnstileMigrationItemStatus::NotStarted) { // Does this z addr have enough balance? + if (fnHasUnconfirmed(nextStep->fromAddr)) { + qDebug() << QString("unconfirmed, waiting"); + return; + } + auto balance = rpc->getAllBalances()->value(nextStep->fromAddr); if (nextStep->amount > balance) { qDebug() << "Not enough balance!"; @@ -306,7 +311,8 @@ void Turnstile::executeMigrationStep() { } else if (nextStep->status == TurnstileMigrationItemStatus::SentToT) { // First thing to do is check to see if the funds are confirmed. - if (fnHasUnconfirmed(nextStep->intTAddr)) { + // We'll check both the original sprout address and the intermediate T addr for safety. + if (fnHasUnconfirmed(nextStep->intTAddr) || fnHasUnconfirmed(nextStep->fromAddr)) { qDebug() << QString("unconfirmed, waiting"); return; } @@ -316,7 +322,7 @@ void Turnstile::executeMigrationStep() { auto sendAmt = bal - Utils::getMinerFee(); if (sendAmt < 0) { - qDebug() << "Not enough balance!"; + qDebug() << "Not enough balance!." << bal << ":" << sendAmt; nextStep->status = TurnstileMigrationItemStatus::NotEnoughBalance; writeMigrationPlan(plan); return;