From c3fcdcb4c513001fa27c3a59f586670aa8cc112e Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Thu, 24 Oct 2019 12:09:27 -0700 Subject: [PATCH] Validate birthday and save wallet at exit --- lib/Cargo.lock | 4 +- src/controller.cpp | 125 ++++++---------------------------------- src/firsttimewizard.cpp | 49 ++++++++++++---- src/liteinterface.cpp | 7 +++ src/liteinterface.h | 4 +- src/restoreseed.ui | 36 ++++++++++++ 6 files changed, 106 insertions(+), 119 deletions(-) diff --git a/lib/Cargo.lock b/lib/Cargo.lock index 4326aef..6f29205 100644 --- a/lib/Cargo.lock +++ b/lib/Cargo.lock @@ -1051,7 +1051,7 @@ version = "0.1.0" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "zecwalletlitelib 0.1.0", + "zecwalletlitelib 0.1.0 (git+https://github.com/adityapk00/zecwallet-light-cli?rev=6dc22e4d74e9cec458d279d793477dea3bfe27e5)", ] [[package]] @@ -2266,6 +2266,7 @@ dependencies = [ [[package]] name = "zecwalletlitelib" version = "0.1.0" +source = "git+https://github.com/adityapk00/zecwallet-light-cli?rev=6dc22e4d74e9cec458d279d793477dea3bfe27e5#6dc22e4d74e9cec458d279d793477dea3bfe27e5" dependencies = [ "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "bellman 0.1.0 (git+https://github.com/adityapk00/librustzcash.git?rev=188537ea025fcb7fbdfc11266f307a084a5451e4)", @@ -2561,3 +2562,4 @@ dependencies = [ "checksum zcash_client_backend 0.0.0 (git+https://github.com/adityapk00/librustzcash.git?rev=188537ea025fcb7fbdfc11266f307a084a5451e4)" = "" "checksum zcash_primitives 0.0.0 (git+https://github.com/adityapk00/librustzcash.git?rev=188537ea025fcb7fbdfc11266f307a084a5451e4)" = "" "checksum zcash_proofs 0.0.0 (git+https://github.com/adityapk00/librustzcash.git?rev=188537ea025fcb7fbdfc11266f307a084a5451e4)" = "" +"checksum zecwalletlitelib 0.1.0 (git+https://github.com/adityapk00/zecwallet-light-cli?rev=6dc22e4d74e9cec458d279d793477dea3bfe27e5)" = "" diff --git a/src/controller.cpp b/src/controller.cpp index dbc1cac..2462c69 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -560,115 +560,28 @@ void Controller::refreshZECPrice() { } void Controller::shutdownZcashd() { - // Shutdown embedded zcashd if it was started - if (ezcashd == nullptr || ezcashd->processId() == 0 || !zrpc->haveConnection()) { - // No zcashd running internally, just return - return; + // Save the wallet and exit the lightclient library cleanly. + if (zrpc->haveConnection()) { + QDialog d(main); + Ui_ConnectionDialog connD; + connD.setupUi(&d); + connD.topIcon->setBasePixmap(QIcon(":/icons/res/icon.ico").pixmap(256, 256)); + connD.status->setText(QObject::tr("Please wait for ZecWallet to exit")); + connD.statusDetail->setText(QObject::tr("Waiting for zcashd to exit")); + + bool finished = false; + + zrpc->saveWallet([&] (json) { + if (!finished) + d.accept(); + finished = true; + }); + + if (!finished) + d.exec(); } - - // json payload = { - // {"jsonrpc", "1.0"}, - // {"id", "someid"}, - // {"method", "stop"} - // }; - - // getConnection()->doRPCWithDefaultErrorHandling(payload, [=](auto) {}); - // getConnection()->shutdown(); - - // QDialog d(main); - // Ui_ConnectionDialog connD; - // connD.setupUi(&d); - // connD.topIcon->setBasePixmap(QIcon(":/icons/res/icon.ico").pixmap(256, 256)); - // connD.status->setText(QObject::tr("Please wait for ZecWallet to exit")); - // connD.statusDetail->setText(QObject::tr("Waiting for zcashd to exit")); - - // QTimer waiter(main); - - // // We capture by reference all the local variables because of the d.exec() - // // below, which blocks this function until we exit. - // int waitCount = 0; - // QObject::connect(&waiter, &QTimer::timeout, [&] () { - // waitCount++; - - // if ((ezcashd->atEnd() && ezcashd->processId() == 0) || - // waitCount > 30 || - // getConnection()->config->zcashDaemon) { // If zcashd is daemon, then we don't have to do anything else - // qDebug() << "Ended"; - // waiter.stop(); - // QTimer::singleShot(1000, [&]() { d.accept(); }); - // } else { - // qDebug() << "Not ended, continuing to wait..."; - // } - // }); - // waiter.start(1000); - - // // Wait for the zcash process to exit. - // if (!Settings::getInstance()->isHeadless()) { - // d.exec(); - // } else { - // while (waiter.isActive()) { - // QCoreApplication::processEvents(); - - // QThread::sleep(1); - // } - // } } - -// // Fetch the Z-board topics list -// void Controller::getZboardTopics(std::function)> cb) { -// if (!zrpc->haveConnection()) -// return noConnection(); - -// QUrl cmcURL("http://z-board.net/listTopics"); - -// QNetworkRequest req; -// req.setUrl(cmcURL); - -// QNetworkReply *reply = conn->restclient->get(req); - -// QObject::connect(reply, &QNetworkReply::finished, [=] { -// reply->deleteLater(); - -// try { -// if (reply->error() != QNetworkReply::NoError) { -// auto parsed = json::parse(reply->readAll(), nullptr, false); -// if (!parsed.is_discarded() && !parsed["error"]["message"].is_null()) { -// qDebug() << QString::fromStdString(parsed["error"]["message"]); -// } -// else { -// qDebug() << reply->errorString(); -// } -// return; -// } - -// auto all = reply->readAll(); - -// auto parsed = json::parse(all, nullptr, false); -// if (parsed.is_discarded()) { -// return; -// } - -// QMap topics; -// for (const json& item : parsed["topics"].get()) { -// if (item.find("addr") == item.end() || item.find("topicName") == item.end()) -// return; - -// QString addr = QString::fromStdString(item["addr"].get()); -// QString topic = QString::fromStdString(item["topicName"].get()); - -// topics.insert(topic, addr); -// } - -// cb(topics); -// } -// catch (...) { -// // If anything at all goes wrong, just set the price to 0 and move on. -// qDebug() << QString("Caught something nasty"); -// } -// }); -// } - /** * Get a Sapling address from the user's wallet */ diff --git a/src/firsttimewizard.cpp b/src/firsttimewizard.cpp index 4d2c8ad..b3cf8a2 100644 --- a/src/firsttimewizard.cpp +++ b/src/firsttimewizard.cpp @@ -135,17 +135,44 @@ bool RestoreSeedPage::validatePage() { return false; } - // 2. Attempt to restore wallet with the seed phrase - char* resp = litelib_initialize_new_from_phrase(parent->dangerous, parent->server.toStdString().c_str(), - seed.toStdString().c_str(), 0); - QString reply = litelib_process_response(resp); - - if (reply.toUpper().trimmed() != "OK") { - QMessageBox::warning(this, tr("Failed to restore wallet"), - tr("Couldn't restore the wallet") + "\n" + reply, + // 2. Validate birthday + QString birthday_str = form.txtBirthday->text(); + bool ok; + qint64 birthday = birthday_str.toUInt(&ok); + if (!ok) { + QMessageBox::warning(this, tr("Failed to parse wallet birthday"), + tr("Couldn't understand wallet birthday. This should be a block height from where to rescan the wallet. You can leave it as '0' if you don't know what it should be."), QMessageBox::Ok); return false; - } else { - return true; - } + } + + // 3. Attempt to restore wallet with the seed phrase + { + char* resp = litelib_initialize_new_from_phrase(parent->dangerous, parent->server.toStdString().c_str(), + seed.toStdString().c_str(), birthday); + QString reply = litelib_process_response(resp); + + if (reply.toUpper().trimmed() != "OK") { + QMessageBox::warning(this, tr("Failed to restore wallet"), + tr("Couldn't restore the wallet") + "\n" + reply, + QMessageBox::Ok); + return false; + } + } + + // 4. Finally attempt to save the wallet + { + char* resp = litelib_execute("save", ""); + QString reply = litelib_process_response(resp); + + auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false); + if (parsed.is_discarded() || parsed.is_null() || parsed.find("result") == parsed.end()) { + QMessageBox::warning(this, tr("Failed to save wallet"), + tr("Couldn't save the wallet") + "\n" + reply, + QMessageBox::Ok); + return false; + } else { + return true; + } + } } \ No newline at end of file diff --git a/src/liteinterface.cpp b/src/liteinterface.cpp index 7fe9580..86fc4fe 100644 --- a/src/liteinterface.cpp +++ b/src/liteinterface.cpp @@ -70,6 +70,13 @@ void LiteInterface::fetchTransactions(const std::function& cb) { conn->doRPCWithDefaultErrorHandling("list", "", cb); } +void LiteInterface::saveWallet(const std::function& cb) { + if (conn == nullptr) + return; + + conn->doRPCWithDefaultErrorHandling("save", "", cb); +} + void LiteInterface::sendTransaction(QString params, const std::function& cb, const std::function& err) { if (conn == nullptr) diff --git a/src/liteinterface.h b/src/liteinterface.h index 6df9662..062c321 100644 --- a/src/liteinterface.h +++ b/src/liteinterface.h @@ -50,7 +50,9 @@ public: void createNewTaddr(const std::function& cb); void fetchPrivKey(QString addr, const std::function& cb); - void fetchAllPrivKeys(const std::function); + void fetchAllPrivKeys(const std::function); + + void saveWallet(const std::function& cb); //void importZPrivKey(QString addr, bool rescan, const std::function& cb); //void importTPrivKey(QString addr, bool rescan, const std::function& cb); diff --git a/src/restoreseed.ui b/src/restoreseed.ui index 2169bcf..9cc2b3f 100644 --- a/src/restoreseed.ui +++ b/src/restoreseed.ui @@ -36,6 +36,13 @@ + + + + Wallet Seed + + + @@ -43,6 +50,35 @@ + + + + Wallet Birthday + + + + + + + 0 + + + + + + + + 9 + + + + Wallet birthday is the block height at which the wallet had the first transaction. If you don't know this, you can leave it as "0" (It'll take longer to rescan) + + + true + + +