diff --git a/lib/Cargo.lock b/lib/Cargo.lock index 1bd2058..fcabaa8 100644 --- a/lib/Cargo.lock +++ b/lib/Cargo.lock @@ -2308,6 +2308,51 @@ dependencies = [ "zcash_primitives 0.0.0 (git+https://github.com/DenioD/librustzcash.git?rev=caaee693c47c2ee9ecd1e1546b8fe3c714f342bc)", ] +[[package]] +name = "silentdragonlitelib" +version = "0.1.0" +source = "git+https://github.com/DenioD/librustzcash.git?rev=caaee693c47c2ee9ecd1e1546b8fe3c714f342bc#caaee693c47c2ee9ecd1e1546b8fe3c714f342bc" +dependencies = [ + "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bellman 0.1.0 (git+https://github.com/DenioD/librustzcash.git?rev=caaee693c47c2ee9ecd1e1546b8fe3c714f342bc)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ff 0.4.0 (git+https://github.com/DenioD/librustzcash.git?rev=caaee693c47c2ee9ecd1e1546b8fe3c714f342bc)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "json 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log4rs 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "pairing 0.14.2 (git+https://github.com/DenioD/librustzcash.git?rev=caaee693c47c2ee9ecd1e1546b8fe3c714f342bc)", + "prost 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-embed 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)", + "secp256k1 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "sodiumoxide 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.10.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tower-grpc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tower-grpc-build 0.1.0 (git+https://github.com/tower-rs/tower-grpc)", + "tower-h2 0.1.0 (git+https://github.com/tower-rs/tower-h2?rev=0865040d699697bbaf1c3b77b3f256b72f98cdf4)", + "tower-request-modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tower-service 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tower-util 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "zcash_client_backend 0.0.0 (git+https://github.com/DenioD/librustzcash.git?rev=caaee693c47c2ee9ecd1e1546b8fe3c714f342bc)", + "zcash_primitives 0.0.0 (git+https://github.com/DenioD/librustzcash.git?rev=caaee693c47c2ee9ecd1e1546b8fe3c714f342bc)", + "zcash_proofs 0.0.0 (git+https://github.com/DenioD/librustzcash.git?rev=caaee693c47c2ee9ecd1e1546b8fe3c714f342bc)", +] + [metadata] "checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" "checksum aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "54eb1d8fe354e5fc611daf4f2ea97dd45a765f4f1e4512306ec183ae2e8f20c9" @@ -2563,3 +2608,4 @@ dependencies = [ "checksum zcash_client_backend 0.0.0 (git+https://github.com/DenioD/librustzcash.git?rev=caaee693c47c2ee9ecd1e1546b8fe3c714f342bc)" = "" "checksum zcash_primitives 0.0.0 (git+https://github.com/DenioD/librustzcash.git?rev=caaee693c47c2ee9ecd1e1546b8fe3c714f342bc)" = "" "checksum zcash_proofs 0.0.0 (git+https://github.com/DenioD/librustzcash.git?rev=caaee693c47c2ee9ecd1e1546b8fe3c714f342bc)" = "" +"checksum silentdragonlitelib 0.1.0 (git+https://github.com/DenioD/silentdragonlite-cli?rev=4d9c09433007e71e259b10f15c28ba1c6ac3efae)" = "" diff --git a/silentdragonlite b/silentdragonlite index 65a8589..292d189 100755 Binary files a/silentdragonlite and b/silentdragonlite differ diff --git a/src/controller.cpp b/src/controller.cpp index 596eaf9..4906d49 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -568,115 +568,28 @@ void Controller::refreshhushPrice() { } void Controller::shutdownhushd() { - // Shutdown embedded hushd if it was started - if (ehushd == nullptr || ehushd->processId() == 0 || !zrpc->haveConnection()) { - // No hushd 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 SilentDragonLite to exit")); + connD.statusDetail->setText(QObject::tr("Waiting for hushd 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 silentdragon to exit")); - // connD.statusDetail->setText(QObject::tr("Waiting for hushd 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 ((ehushd->atEnd() && ehushd->processId() == 0) || - // waitCount > 30 || - // getConnection()->config->hushDaemon) { // If hushd 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 hush 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 6d7f387..20bae10 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 507b781..de77a7b 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 59ef16c..860824c 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 + + +