Handle edge cases for sapling activation

This commit is contained in:
Aditya Kulkarni
2018-10-28 22:36:49 -07:00
parent 887b78758d
commit e5d2ae7d9b
8 changed files with 83 additions and 43 deletions

View File

@@ -75,8 +75,6 @@ void MainWindow::turnstileProgress() {
QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning); QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning);
progress.msgIcon->setPixmap(icon.pixmap(64, 64)); progress.msgIcon->setPixmap(icon.pixmap(64, 64));
progress.buttonBox->button(QDialogButtonBox::Cancel)->setText("Abort");
auto fnUpdateProgressUI = [=] () { auto fnUpdateProgressUI = [=] () {
// Get the plan progress // Get the plan progress
if (rpc->getTurnstile()->isMigrationPresent()) { if (rpc->getTurnstile()->isMigrationPresent()) {
@@ -112,20 +110,31 @@ void MainWindow::turnstileProgress() {
progressTimer.start(Utils::updateSpeed); progressTimer.start(Utils::updateSpeed);
fnUpdateProgressUI(); fnUpdateProgressUI();
auto accpeted = d.exec();
auto curProgress = rpc->getTurnstile()->getPlanProgress(); auto curProgress = rpc->getTurnstile()->getPlanProgress();
// Abort button
if (curProgress.step != curProgress.totalSteps)
progress.buttonBox->button(QDialogButtonBox::Discard)->setText("Abort");
else
progress.buttonBox->button(QDialogButtonBox::Discard)->setVisible(false);
QObject::connect(progress.buttonBox->button(QDialogButtonBox::Discard), &QPushButton::clicked, [&] () {
if (curProgress.step != curProgress.totalSteps) {
auto abort = QMessageBox::warning(this, "Are you sure you want to Abort?",
"Are you sure you want to abort the migration?\nAll further transactions will be cancelled.\nAll your funds are still in your wallet.",
QMessageBox::Yes, QMessageBox::No);
if (abort == QMessageBox::Yes) {
rpc->getTurnstile()->removeFile();
d.close();
ui->statusBar->showMessage("Automatic Sapling turnstile migration aborted.");
}
}
});
auto accpeted = d.exec();
if (accpeted == QDialog::Accepted && curProgress.step == curProgress.totalSteps) { if (accpeted == QDialog::Accepted && curProgress.step == curProgress.totalSteps) {
// Finished, so delete the file // Finished, so delete the file
rpc->getTurnstile()->removeFile(); rpc->getTurnstile()->removeFile();
} }
if (accpeted == QDialog::Rejected && curProgress.step != curProgress.totalSteps) {
auto abort = QMessageBox::warning(this, "Are you sure you want to Abort?",
"Are you sure you want to abort the migration?\nAll further transactions will be cancelled.\nAll your funds are still in your wallet.",
QMessageBox::Yes, QMessageBox::No);
if (abort) {
rpc->getTurnstile()->removeFile();
}
}
} }
void MainWindow::turnstileDoMigration() { void MainWindow::turnstileDoMigration() {
@@ -158,7 +167,7 @@ void MainWindow::turnstileDoMigration() {
} }
} }
QObject::connect(turnstile.migrateZaddList, &QComboBox::currentTextChanged, [=] (auto addr) { auto fnUpdateSproutBalance = [=] (QString addr) {
double bal = 0; double bal = 0;
if (addr.startsWith("All")) { if (addr.startsWith("All")) {
bal = fnGetAllSproutBalance(); bal = fnGetAllSproutBalance();
@@ -166,8 +175,25 @@ void MainWindow::turnstileDoMigration() {
bal = rpc->getAllBalances()->value(addr); bal = rpc->getAllBalances()->value(addr);
} }
turnstile.fromBalance->setText(Settings::getInstance()->getZECUSDDisplayFormat(bal)); auto balTxt = Settings::getInstance()->getZECUSDDisplayFormat(bal);
});
if (bal < Turnstile::minMigrationAmount) {
turnstile.fromBalance->setStyleSheet("color: red;");
turnstile.fromBalance->setText(balTxt % " [You need at least "
% Settings::getInstance()->getZECDisplayFormat(Turnstile::minMigrationAmount)
% " for automatic migration]");
turnstile.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
} else {
turnstile.fromBalance->setStyleSheet("");
turnstile.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
turnstile.fromBalance->setText(balTxt);
}
};
fnUpdateSproutBalance(turnstile.migrateZaddList->currentText());
// Combo box selection event
QObject::connect(turnstile.migrateZaddList, &QComboBox::currentTextChanged, fnUpdateSproutBalance);
// Privacy level combobox // Privacy level combobox
// Num tx over num blocks // Num tx over num blocks
@@ -196,7 +222,7 @@ void MainWindow::turnstileDoMigration() {
privLevel.first, privLevel.second); privLevel.first, privLevel.second);
QMessageBox::information(this, "Backup your wallet.dat", 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.", "The migration will now start. You can check progress in the File -> Sapling Turnstile 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); QMessageBox::Ok);
} }
} }

View File

@@ -22,7 +22,7 @@
<item row="0" column="0"> <item row="0" column="0">
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>1</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="tab"> <widget class="QWidget" name="tab">
<attribute name="title"> <attribute name="title">
@@ -778,7 +778,7 @@
</action> </action>
<action name="actionTurnstile_Migration"> <action name="actionTurnstile_Migration">
<property name="text"> <property name="text">
<string>Turnstile Migration</string> <string>Sapling Turnstile</string>
</property> </property>
</action> </action>
</widget> </widget>

View File

@@ -11,7 +11,7 @@ RPC::RPC(QNetworkAccessManager* client, MainWindow* main) {
this->main = main; this->main = main;
this->ui = main->ui; this->ui = main->ui;
this->turnstile = new Turnstile(this); this->turnstile = new Turnstile(this, main);
// Setup balances table model // Setup balances table model
balancesTableModel = new BalancesTableModel(main->ui->balancesTable); balancesTableModel = new BalancesTableModel(main->ui->balancesTable);
@@ -510,8 +510,13 @@ void RPC::refreshAddresses() {
// Function to create the data model and update the views, used below. // Function to create the data model and update the views, used below.
void RPC::updateUI(bool anyUnconfirmed) { void RPC::updateUI(bool anyUnconfirmed) {
// See if the turnstile migration has any steps that need to be done. if (Settings::getInstance()->isTestnet()) {
turnstile->executeMigrationStep(); // See if the turnstile migration has any steps that need to be done.
turnstile->executeMigrationStep();
} else {
// Not available on mainnet yet.
main->ui->actionTurnstile_Migration->setVisible(false);
}
ui->unconfirmedWarning->setVisible(anyUnconfirmed); ui->unconfirmedWarning->setVisible(anyUnconfirmed);

View File

@@ -9,8 +9,9 @@
using json = nlohmann::json; using json = nlohmann::json;
Turnstile::Turnstile(RPC* _rpc) { Turnstile::Turnstile(RPC* _rpc, QWidget* mainwindow) {
this->rpc = _rpc; this->rpc = _rpc;
this->mainwindow = mainwindow;
} }
Turnstile::~Turnstile() { Turnstile::~Turnstile() {
@@ -117,6 +118,13 @@ void Turnstile::planMigration(QString zaddr, QString destAddr, int numsplits, in
// The first migration is shifted to the current block, so the user sees something // The first migration is shifted to the current block, so the user sees something
// happening immediately // happening immediately
if (migItems.size() == 0) {
// Show error and abort
QMessageBox::warning(mainwindow,
"Locked funds", "Could not initiate migration.\nYou either have unconfirmed funds or the balance is too low for an automatic migration.");
return;
}
migItems[0].blockNumber = curBlock; migItems[0].blockNumber = curBlock;
std::sort(migItems.begin(), migItems.end(), [&] (auto a, auto b) { std::sort(migItems.begin(), migItems.end(), [&] (auto a, auto b) {
@@ -124,7 +132,7 @@ void Turnstile::planMigration(QString zaddr, QString destAddr, int numsplits, in
}); });
writeMigrationPlan(migItems); writeMigrationPlan(migItems);
auto readPlan = readMigrationPlan(); rpc->refresh(true); // Force refresh, to start the migration immediately
} }
); );
} }
@@ -141,10 +149,13 @@ QList<int> Turnstile::getBlockNumbers(int start, int end, int count) {
return blocks; return blocks;
} }
// Need at least 0.0005 ZEC for this
double Turnstile::minMigrationAmount = 0.0005;
QList<double> Turnstile::splitAmount(double amount, int parts) { QList<double> Turnstile::splitAmount(double amount, int parts) {
QList<double> amounts; QList<double> amounts;
// Need at least 0.0004 ZEC for this
if (amount < 0.0004) if (amount < minMigrationAmount)
return amounts; return amounts;
fillAmounts(amounts, amount, parts); fillAmounts(amounts, amount, parts);
@@ -201,14 +212,6 @@ Turnstile::getNextStep(QList<TurnstileMigrationItem>& plan) {
item.status == TurnstileMigrationItemStatus::SentToT; 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 // Find the next step
auto nextStep = std::find_if(plan.begin(), plan.end(), fnIsEligibleItem); auto nextStep = std::find_if(plan.begin(), plan.end(), fnIsEligibleItem);
return nextStep; return nextStep;

View File

@@ -33,7 +33,7 @@ struct ProgressReport {
class Turnstile class Turnstile
{ {
public: public:
Turnstile(RPC* _rpc); Turnstile(RPC* _rpc, QWidget* mainwindow);
~Turnstile(); ~Turnstile();
void planMigration(QString zaddr, QString destAddr, int splits, int numBlocks); void planMigration(QString zaddr, QString destAddr, int splits, int numBlocks);
@@ -48,6 +48,7 @@ public:
ProgressReport getPlanProgress(); ProgressReport getPlanProgress();
bool isMigrationPresent(); bool isMigrationPresent();
static double minMigrationAmount;
private: private:
QList<int> getBlockNumbers(int start, int end, int count); QList<int> getBlockNumbers(int start, int end, int count);
QString writeableFile(); QString writeableFile();
@@ -57,7 +58,8 @@ private:
QList<TurnstileMigrationItem>::Iterator getNextStep(QList<TurnstileMigrationItem>& plan); QList<TurnstileMigrationItem>::Iterator getNextStep(QList<TurnstileMigrationItem>& plan);
RPC* rpc; RPC* rpc;
QWidget* mainwindow;
}; };
#endif #endif

View File

@@ -30,7 +30,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text"> <property name="text">
<string>Please Ensure you have your wallet.dat backed up!</string> <string>Please ensure you have your wallet.dat backed up!</string>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
@@ -90,7 +90,10 @@
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="standardButtons"> <property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> <set>QDialogButtonBox::Close|QDialogButtonBox::Discard|QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>false</bool>
</property> </property>
</widget> </widget>
</item> </item>

View File

@@ -681,7 +681,7 @@ public:
retranslateUi(MainWindow); retranslateUi(MainWindow);
tabWidget->setCurrentIndex(1); tabWidget->setCurrentIndex(0);
QMetaObject::connectSlotsByName(MainWindow); QMetaObject::connectSlotsByName(MainWindow);
@@ -696,7 +696,7 @@ public:
actionDonate->setText(QApplication::translate("MainWindow", "Donate", nullptr)); actionDonate->setText(QApplication::translate("MainWindow", "Donate", nullptr));
actionImport_Private_Keys->setText(QApplication::translate("MainWindow", "Import Private Keys", 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)); actionCheck_for_Updates->setText(QApplication::translate("MainWindow", "Check github.com for Updates", nullptr));
actionTurnstile_Migration->setText(QApplication::translate("MainWindow", "Turnstile Migration", nullptr)); actionTurnstile_Migration->setText(QApplication::translate("MainWindow", "Sapling Turnstile", nullptr));
groupBox->setTitle(QApplication::translate("MainWindow", "Summary", nullptr)); groupBox->setTitle(QApplication::translate("MainWindow", "Summary", nullptr));
label->setText(QApplication::translate("MainWindow", "Shielded", nullptr)); label->setText(QApplication::translate("MainWindow", "Shielded", nullptr));
balSheilded->setText(QString()); balSheilded->setText(QString());

View File

@@ -97,7 +97,8 @@ public:
buttonBox = new QDialogButtonBox(TurnstileProgress); buttonBox = new QDialogButtonBox(TurnstileProgress);
buttonBox->setObjectName(QStringLiteral("buttonBox")); buttonBox->setObjectName(QStringLiteral("buttonBox"));
buttonBox->setOrientation(Qt::Horizontal); buttonBox->setOrientation(Qt::Horizontal);
buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); buttonBox->setStandardButtons(QDialogButtonBox::Close|QDialogButtonBox::Discard|QDialogButtonBox::Ok);
buttonBox->setCenterButtons(false);
gridLayout->addWidget(buttonBox, 9, 0, 1, 3); gridLayout->addWidget(buttonBox, 9, 0, 1, 3);
@@ -123,7 +124,7 @@ public:
void retranslateUi(QDialog *TurnstileProgress) void retranslateUi(QDialog *TurnstileProgress)
{ {
TurnstileProgress->setWindowTitle(QApplication::translate("TurnstileProgress", "Turnstile Migration Progress", nullptr)); TurnstileProgress->setWindowTitle(QApplication::translate("TurnstileProgress", "Turnstile Migration Progress", nullptr));
label_4->setText(QApplication::translate("TurnstileProgress", "Please Ensure you have your wallet.dat backed up!", nullptr)); label_4->setText(QApplication::translate("TurnstileProgress", "Please ensure you have your wallet.dat backed up!", nullptr));
nextTx->setText(QApplication::translate("TurnstileProgress", "Next Transaction in 4 hours", nullptr)); nextTx->setText(QApplication::translate("TurnstileProgress", "Next Transaction in 4 hours", nullptr));
progressTxt->setText(QApplication::translate("TurnstileProgress", "4 / 12", nullptr)); progressTxt->setText(QApplication::translate("TurnstileProgress", "4 / 12", nullptr));
label_2->setText(QApplication::translate("TurnstileProgress", "Migration Progress", nullptr)); label_2->setText(QApplication::translate("TurnstileProgress", "Migration Progress", nullptr));