From 1e9289095f7298f650a1d9e910b8ffafb87d0aab Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Fri, 2 Nov 2018 21:51:04 -0700 Subject: [PATCH 01/23] cretae zcash.conf and get params --- src/connection.cpp | 134 ++++++++++++++++++++++++++++++++++++++------- src/connection.h | 7 +++ src/main.cpp | 4 ++ src/precompiled.h | 1 + src/settings.h | 8 +++ 5 files changed, 133 insertions(+), 21 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index 1745e33..6ef11bb 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -30,26 +30,105 @@ ConnectionLoader::~ConnectionLoader() { } void ConnectionLoader::loadConnection() { + // Load from settings if it is a manual connection. + if (Settings::getInstance()->getIsManualConnection()) { + doManualConnect(); + } else { + doAutoConnect(); + } +} + +void ConnectionLoader::doAutoConnect() { // Priority 1: Try to connect to detect zcash.conf and connect to it. auto config = autoDetectZcashConf(); - // If not autodetected, go and read the UI Settings - if (config.get() == nullptr) { - config = loadFromSettings(); + if (config.get() != nullptr) { + auto connection = makeConnection(config); + refreshZcashdState(connection); - if (config.get() == nullptr) { - d->show(); - // Nothing configured, show an error - QString explanation = QString() - % "A zcash.conf was not found on this machine.\n\n" - % "If you are connecting to a remote/non-standard node " - % "please set the host/port and user/password in the File->Settings menu."; + return; + } else { + // zcash.conf was not found, so create one + createZcashConf(); + } +} - showError(explanation); - doRPCSetConnection(nullptr); +/** + * This will create a new zcash.conf, download zcash parameters. + */ +void ConnectionLoader::createZcashConf() { + // Create zcash.conf + { + auto confLocation = zcashConfWritableLocation(); + qDebug() << "Creating file " << confLocation; - return; - } + QFileInfo fi(confLocation); + QDir().mkdir(fi.dir().absolutePath()); + + QFile file(confLocation); + file.open(QIODevice::ReadWrite | QIODevice::Truncate); + QTextStream out(&file); + + out << "server=1\n"; + out << "rpcuser=zec-qt-wallet\n"; + out << "rpcpassword=" % QString::number(std::rand()) << "\n"; + file.close(); + } + + // Fetch params. + { + QFileInfo fi(Settings::getInstance()->getExecName()); + auto fetchParamsProgram = fi.dir().filePath("zcash-fetch-params"); + + QProcess* p = new QProcess(main); + QObject::connect(p, &QProcess::readyReadStandardOutput, [=] () { + qDebug() << "stdout:" << p->readAllStandardOutput(); + }); + QObject::connect(p, QOverload::of(&QProcess::finished), + [=](int exitCode, QProcess::ExitStatus exitStatus) { + qDebug() << "finished with code " << exitCode; + p->deleteLater(); + }); + p->start(fetchParamsProgram); + + // stdout: "Zcash - fetch-params.sh\n\nThis script will fetch the Zcash zkSNARK parameters and verify their\nintegrity with sha256sum.\n\nIf they already exist locally, it will exit now and do nothing else.\nThe parameters are currently just under 911MB in size, so plan accordingly\nfor your bandwidth constraints. If the files are already present and\nhave the correct sha256sum, no networking is used.\n\nCreating params directory. For details about this directory, see:\n/home/adityapk/.zcash-params/README\n\n\nRetrieving (wget): https://z.cash/downloads/sprout-proving.key\n" + // stdout: "Download successful!\n" + // stdout: "/home/adityapk/.zcash-params/sprout-proving.key.dl: OK\n" + // stdout: "renamed '/home/adityapk/.zcash-params/sprout-proving.key.dl' -> '/home/adityapk/.zcash-params/sprout-proving.key'\n" + // stdout: "\nRetrieving (wget): https://z.cash/downloads/sprout-verifying.key\n" + // stdout: "Download successful!\n" + // stdout: "/home/adityapk/.zcash-params/sprout-verifying.key.dl: OK\n" + // stdout: "renamed '/home/adityapk/.zcash-params/sprout-verifying.key.dl' -> '/home/adityapk/.zcash-params/sprout-verifying.key'\n" + // stdout: "\nRetrieving (wget): https://z.cash/downloads/sapling-spend.params\n" + // stdout: "Download successful!\n" + // stdout: "/home/adityapk/.zcash-params/sapling-spend.params.dl: OK\n" + // stdout: "renamed '/home/adityapk/.zcash-params/sapling-spend.params.dl' -> '/home/adityapk/.zcash-params/sapling-spend.params'\n" + // stdout: "\nRetrieving (wget): https://z.cash/downloads/sapling-output.params\n" + // stdout: "Download successful!\n" + // stdout: "/home/adityapk/.zcash-params/sapling-output.params.dl: OK\n" + // stdout: "renamed '/home/adityapk/.zcash-params/sapling-output.params.dl' -> '/home/adityapk/.zcash-params/sapling-output.params'\n" + // stdout: "\nRetrieving (wget): https://z.cash/downloads/sprout-groth16.params\n" + // stdout: "Download successful!\n" + // stdout: "/home/adityapk/.zcash-params/sprout-groth16.params.dl: OK\n" + // stdout: "renamed '/home/adityapk/.zcash-params/sprout-groth16.params.dl' -> '/home/adityapk/.zcash-params/sprout-groth16.params'\n" + // finished with code 0 + } +} + +void ConnectionLoader::doManualConnect() { + auto config = loadFromSettings(); + + if (config.get() == nullptr) { + d->show(); + // Nothing configured, show an error + QString explanation = QString() + % "A manual connection was requested, but the settings are not configured.\n\n" + % "Please set the host/port and user/password in the File->Settings menu."; + + showError(explanation); + doRPCSetConnection(nullptr); + + return; } auto connection = makeConnection(config); @@ -137,12 +216,7 @@ void ConnectionLoader::showError(QString explanation) { connD->buttonBox->setEnabled(true); } - -/** - * Try to automatically detect a zcash.conf file in the correct location and load parameters - */ -std::shared_ptr ConnectionLoader::autoDetectZcashConf() { - +QString ConnectionLoader::locateZcashConfFile() { #ifdef Q_OS_LINUX auto confLocation = QStandardPaths::locate(QStandardPaths::HomeLocation, ".zcash/zcash.conf"); #elif defined(Q_OS_DARWIN) @@ -150,8 +224,26 @@ std::shared_ptr ConnectionLoader::autoDetectZcashConf() { #else auto confLocation = QStandardPaths::locate(QStandardPaths::AppDataLocation, "../../Zcash/zcash.conf"); #endif + return QDir::cleanPath(confLocation); +} - confLocation = QDir::cleanPath(confLocation); +QString ConnectionLoader::zcashConfWritableLocation() { +#ifdef Q_OS_LINUX + auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath(".zcash/zcash.conf"); +#elif defined(Q_OS_DARWIN) + auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath("/Library/Application Support/Zcash/zcash.conf"); +#else + auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("../../Zcash/zcash.conf"); +#endif + + return confLocation; +} + +/** + * Try to automatically detect a zcash.conf file in the correct location and load parameters + */ +std::shared_ptr ConnectionLoader::autoDetectZcashConf() { + auto confLocation = locateZcashConfFile(); if (confLocation.isNull()) { // No zcash file, just return with nothing diff --git a/src/connection.h b/src/connection.h index d6c26a9..2b3c215 100644 --- a/src/connection.h +++ b/src/connection.h @@ -41,6 +41,13 @@ private: Connection* makeConnection(std::shared_ptr config); + void doAutoConnect(); + void doManualConnect(); + + void createZcashConf(); + QString locateZcashConfFile(); + QString zcashConfWritableLocation(); + void refreshZcashdState(Connection* connection); int getProgressFromStatus(QString status); diff --git a/src/main.cpp b/src/main.cpp index 36febd2..898fc77 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,6 +21,10 @@ int main(int argc, char *argv[]) std::srand(std::time(nullptr)); Settings::init(); + if (argc >= 2 && QString::fromStdString(argv[1]) == "-manual") { + Settings::getInstance()->setManualConnection(true); + } + QCoreApplication::setOrganizationName("zec-qt-wallet-org"); QCoreApplication::setApplicationName("zec-qt-wallet"); diff --git a/src/precompiled.h b/src/precompiled.h index 34e5b02..c0dc783 100644 --- a/src/precompiled.h +++ b/src/precompiled.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include diff --git a/src/settings.h b/src/settings.h index b771293..ecb980a 100644 --- a/src/settings.h +++ b/src/settings.h @@ -29,6 +29,12 @@ public: bool isSyncing(); void setSyncing(bool syncing); + bool getIsManualConnection() { return _manualConn; } + void setManualConnection(bool manual) {_manualConn = manual;} + + QString getExecName() { return _executable; } + void setExecName(QString name) { _executable = name; } + int getBlockNumber(); void setBlockNumber(int number); @@ -56,9 +62,11 @@ private: static Settings* instance; QString _confLocation; + QString _executable; bool _isTestnet = false; bool _isSyncing = false; int _blockNumber = 0; + bool _manualConn = false; double zecPrice = 0.0; }; From 46f2f7f02ee33a6cbbeb1f7d7bec7ffd591adbe1 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Fri, 2 Nov 2018 22:20:31 -0700 Subject: [PATCH 02/23] autostart zcashd --- src/connection.cpp | 91 +++++++++++++++++++++++++++++++++++++++------- src/connection.h | 3 ++ src/mainwindow.cpp | 4 ++ src/rpc.cpp | 16 ++++++++ src/rpc.h | 4 ++ src/settings.h | 12 ++++-- 6 files changed, 113 insertions(+), 17 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index 6ef11bb..b8700e5 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -66,7 +66,11 @@ void ConnectionLoader::createZcashConf() { QDir().mkdir(fi.dir().absolutePath()); QFile file(confLocation); - file.open(QIODevice::ReadWrite | QIODevice::Truncate); + if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) { + qDebug() << "Could not create zcash.conf, returning"; + return; + } + QTextStream out(&file); out << "server=1\n"; @@ -113,6 +117,53 @@ void ConnectionLoader::createZcashConf() { // stdout: "renamed '/home/adityapk/.zcash-params/sprout-groth16.params.dl' -> '/home/adityapk/.zcash-params/sprout-groth16.params'\n" // finished with code 0 } + + { + startEmbeddedZcashd(); + + auto config = autoDetectZcashConf(); + if (config.get() != nullptr) { + auto connection = makeConnection(config); + refreshZcashdState(connection); + + return; + } else { + qDebug() << "Coulnd't get embedded startup zcashd"; + } + } +} + +bool ConnectionLoader::startEmbeddedZcashd() { + static bool erroredOut = false; + + if (erroredOut) { + qDebug() << "Last zcashd start attempted errored, so not restarting"; + return false; + } + + // Finally, start zcashd + qDebug() << "Starting zcashd"; + QFileInfo fi(Settings::getInstance()->getExecName()); + auto zcashdProgram = fi.dir().filePath("zcashd"); + + QProcess* p = new QProcess(main); + QObject::connect(p, &QProcess::started, [=] () { + Settings::getInstance()->setEmbeddedZcashdRunning(true); + }); + + QObject::connect(p, QOverload::of(&QProcess::finished), + [=](int exitCode, QProcess::ExitStatus exitStatus) { + qDebug() << "zcashd finished with code " << exitCode; + p->deleteLater(); + }); + + QObject::connect(p, &QProcess::errorOccurred, [&] (auto error) mutable { + qDebug() << "Couldn't start zcashd: " << error; + erroredOut = true; + }); + + p->start(zcashdProgram); + return true; } void ConnectionLoader::doManualConnect() { @@ -178,15 +229,26 @@ void ConnectionLoader::refreshZcashdState(Connection* connection) { // Failed, see what it is. //qDebug() << err << ":" << QString::fromStdString(res.dump()); - if (err == QNetworkReply::NetworkError::ConnectionRefusedError) { - auto isZcashConfFound = connection->config.get()->usingZcashConf; - QString explanation = QString() - % (isZcashConfFound ? "A zcash.conf file was found, but a" : "A") - % " connection to zcashd could not be established.\n\n" - % "If you are connecting to a remote/non-standard node " - % "please set the host/port and user/password in the File->Settings menu"; + if (err == QNetworkReply::NetworkError::ConnectionRefusedError) { + // Start embedded zcasd + this->showInformation("Starting Embedded zcashd"); + if (this->startEmbeddedZcashd()) { + // Refresh after one second + QTimer::singleShot(1000, [=]() { this->refreshZcashdState(connection); }); + } else { + // Errored out, show error and exit + QString explanation = "Couldn't start zcashd"; + this->showError(explanation); + } - this->showError(explanation); + // auto isZcashConfFound = connection->config.get()->usingZcashConf; + // QString explanation = QString() + // % (isZcashConfFound ? "A zcash.conf file was found, but a" : "A") + // % " connection to zcashd could not be established.\n\n" + // % "If you are connecting to a remote/non-standard node " + // % "please set the host/port and user/password in the File->Settings menu"; + + // this->showError(explanation); } else if (err == QNetworkReply::NetworkError::AuthenticationRequiredError) { QString explanation = QString() % "Authentication failed. The username / password you specified was " @@ -196,10 +258,7 @@ void ConnectionLoader::refreshZcashdState(Connection* connection) { } else if (err == QNetworkReply::NetworkError::InternalServerError && !res.is_discarded()) { // The server is loading, so just poll until it succeeds QString status = QString::fromStdString(res["error"]["message"]); - - QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); - connD->icon->setPixmap(icon.pixmap(128, 128)); - connD->status->setText("Your zcashd is starting up. Please wait.\n\n" % status); + showInformation("Your zcashd is starting up. Please wait.\n\n" % status); // Refresh after one second QTimer::singleShot(1000, [=]() { this->refreshZcashdState(connection); }); @@ -208,6 +267,12 @@ void ConnectionLoader::refreshZcashdState(Connection* connection) { ); } +void ConnectionLoader::showInformation(QString info) { + QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); + connD->icon->setPixmap(icon.pixmap(128, 128)); + connD->status->setText(info); +} + void ConnectionLoader::showError(QString explanation) { QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical); connD->icon->setPixmap(icon.pixmap(128, 128)); diff --git a/src/connection.h b/src/connection.h index 2b3c215..21f3f71 100644 --- a/src/connection.h +++ b/src/connection.h @@ -48,10 +48,13 @@ private: QString locateZcashConfFile(); QString zcashConfWritableLocation(); + bool startEmbeddedZcashd(); + void refreshZcashdState(Connection* connection); int getProgressFromStatus(QString status); void showError(QString explanation); + void showInformation(QString info); void doRPCSetConnection(Connection* conn); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index dd7ad6f..7adfe59 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -88,6 +88,10 @@ void MainWindow::closeEvent(QCloseEvent* event) { s.setValue("baltablegeometry", ui->balancesTable->horizontalHeader()->saveState()); s.setValue("tratablegeometry", ui->transactionsTable->horizontalHeader()->saveState()); + // Let the RPC know to shutdown any running service. + rpc->closeEvent(); + + // Bubble up QMainWindow::closeEvent(event); } diff --git a/src/rpc.cpp b/src/rpc.cpp index f3dc59c..bc107c6 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -807,3 +807,19 @@ void RPC::refreshZECPrice() { Settings::getInstance()->setZECPrice(0); }); } + +void RPC::shutdownZcashd() { + json payload = { + {"jsonrpc", "1.0"}, + {"id", "someid"}, + {"method", "stop"} + }; + + conn->doRPCWithDefaultErrorHandling(payload, [=](auto) {}); +} + +void RPC::closeEvent() { + if (Settings::getInstance()->isEmbeddedZcashdRunning()) { + shutdownZcashd(); + } +} \ No newline at end of file diff --git a/src/rpc.h b/src/rpc.h index 6ec7df7..d8dde07 100644 --- a/src/rpc.h +++ b/src/rpc.h @@ -56,11 +56,15 @@ public: void importZPrivKey(QString addr, bool rescan, const std::function& cb); void importTPrivKey(QString addr, bool rescan, const std::function& cb); + void shutdownZcashd(); + void getAllPrivKeys(const std::function>)>); Turnstile* getTurnstile() { return turnstile; } Connection* getConnection() { return conn; } + void closeEvent(); + private: void noConnection(); diff --git a/src/settings.h b/src/settings.h index ecb980a..de7ebb8 100644 --- a/src/settings.h +++ b/src/settings.h @@ -35,6 +35,9 @@ public: QString getExecName() { return _executable; } void setExecName(QString name) { _executable = name; } + void setEmbeddedZcashdRunning(bool r) { _isEmbeddedZcashd = r; } + bool isEmbeddedZcashdRunning() { return _isEmbeddedZcashd; } + int getBlockNumber(); void setBlockNumber(int number); @@ -63,10 +66,11 @@ private: QString _confLocation; QString _executable; - bool _isTestnet = false; - bool _isSyncing = false; - int _blockNumber = 0; - bool _manualConn = false; + bool _isTestnet = false; + bool _isSyncing = false; + int _blockNumber = 0; + bool _manualConn = false; + bool _isEmbeddedZcashd = false; double zecPrice = 0.0; }; From ce16f53f691999390ce93189be42b4ba9ecbe429 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Fri, 2 Nov 2018 23:15:39 -0700 Subject: [PATCH 03/23] close zcashd properly at exit --- src/connection.cpp | 34 ++++++++++++++++++++-------------- src/connection.h | 2 ++ src/mainwindow.cpp | 2 +- src/rpc.cpp | 33 ++++++++++++++++++++++++++------- src/rpc.h | 3 ++- 5 files changed, 51 insertions(+), 23 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index b8700e5..159681c 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -134,11 +134,13 @@ void ConnectionLoader::createZcashConf() { } bool ConnectionLoader::startEmbeddedZcashd() { - static bool erroredOut = false; - - if (erroredOut) { - qDebug() << "Last zcashd start attempted errored, so not restarting"; - return false; + if (ezcashd != nullptr) { + if (ezcashd->state() == QProcess::NotRunning) { + qDebug() << "Process started and then crashed"; + return false; + } else { + return true; + } } // Finally, start zcashd @@ -146,23 +148,23 @@ bool ConnectionLoader::startEmbeddedZcashd() { QFileInfo fi(Settings::getInstance()->getExecName()); auto zcashdProgram = fi.dir().filePath("zcashd"); - QProcess* p = new QProcess(main); - QObject::connect(p, &QProcess::started, [=] () { + ezcashd = new QProcess(main); + QObject::connect(ezcashd, &QProcess::started, [=] () { + qDebug() << "zcashd started"; Settings::getInstance()->setEmbeddedZcashdRunning(true); }); - QObject::connect(p, QOverload::of(&QProcess::finished), + QObject::connect(ezcashd, QOverload::of(&QProcess::finished), [=](int exitCode, QProcess::ExitStatus exitStatus) { - qDebug() << "zcashd finished with code " << exitCode; - p->deleteLater(); + qDebug() << "zcashd finished with code " << exitCode << "," << exitStatus; }); - QObject::connect(p, &QProcess::errorOccurred, [&] (auto error) mutable { + QObject::connect(ezcashd, &QProcess::errorOccurred, [&] (auto error) mutable { qDebug() << "Couldn't start zcashd: " << error; - erroredOut = true; }); - p->start(zcashdProgram); + ezcashd->start(zcashdProgram); + return true; } @@ -187,6 +189,10 @@ void ConnectionLoader::doManualConnect() { } void ConnectionLoader::doRPCSetConnection(Connection* conn) { + if (ezcashd != nullptr) { + rpc->setEZcashd(ezcashd); + } + rpc->setConnection(conn); delete this; } @@ -257,7 +263,7 @@ void ConnectionLoader::refreshZcashdState(Connection* connection) { this->showError(explanation); } else if (err == QNetworkReply::NetworkError::InternalServerError && !res.is_discarded()) { // The server is loading, so just poll until it succeeds - QString status = QString::fromStdString(res["error"]["message"]); + QString status = QString::fromStdString(res["error"]["message"]); showInformation("Your zcashd is starting up. Please wait.\n\n" % status); // Refresh after one second diff --git a/src/connection.h b/src/connection.h index 21f3f71..ccdd163 100644 --- a/src/connection.h +++ b/src/connection.h @@ -58,6 +58,8 @@ private: void doRPCSetConnection(Connection* conn); + QProcess* ezcashd = nullptr; + QDialog* d; Ui_ConnectionDialog* connD; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 7adfe59..f02588a 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -89,7 +89,7 @@ void MainWindow::closeEvent(QCloseEvent* event) { s.setValue("tratablegeometry", ui->transactionsTable->horizontalHeader()->saveState()); // Let the RPC know to shutdown any running service. - rpc->closeEvent(); + rpc->shutdownZcashd(); // Bubble up QMainWindow::closeEvent(event); diff --git a/src/rpc.cpp b/src/rpc.cpp index bc107c6..fa205b9 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -62,6 +62,10 @@ RPC::~RPC() { delete conn; } +void RPC::setEZcashd(QProcess* p) { + ezcashd = p; +} + void RPC::setConnection(Connection* c) { if (c == nullptr) return; @@ -478,7 +482,7 @@ void RPC::getInfoThenRefresh(bool force) { conn->doRPCIgnoreError(payload, [=](const json& reply) { auto progress = reply["verificationprogress"].get(); - bool isSyncing = progress < 0.999; // 99.9% + bool isSyncing = progress < 0.995; // 99.59% int blockNumber = reply["blocks"].get(); Settings::getInstance()->setSyncing(isSyncing); @@ -816,10 +820,25 @@ void RPC::shutdownZcashd() { }; conn->doRPCWithDefaultErrorHandling(payload, [=](auto) {}); -} -void RPC::closeEvent() { - if (Settings::getInstance()->isEmbeddedZcashdRunning()) { - shutdownZcashd(); - } -} \ No newline at end of file + QMessageBox d(main); + d.setIcon(QMessageBox::Icon::Information); + d.setWindowTitle("Waiting for zcashd to exit"); + d.setText("Please wait for zcashd to exit. Don't click OK!"); + d.setStandardButtons(QMessageBox::NoButton); + d.setWindowFlags(Qt::SplashScreen); + + QTimer waiter(main); + QObject::connect(&waiter, &QTimer::timeout, [&] () { + if (ezcashd->atEnd()) { + qDebug() << "Ended"; + d.accept(); + } else { + qDebug() << "Not ended"; + } + }); + waiter.start(1000); + + // Wait for the zcash process to exit. + d.exec(); +} diff --git a/src/rpc.h b/src/rpc.h index d8dde07..3ededd6 100644 --- a/src/rpc.h +++ b/src/rpc.h @@ -32,6 +32,7 @@ public: ~RPC(); void setConnection(Connection* c); + void setEZcashd(QProcess* p); void refresh(bool force = false); @@ -63,7 +64,6 @@ public: Turnstile* getTurnstile() { return turnstile; } Connection* getConnection() { return conn; } - void closeEvent(); private: void noConnection(); @@ -90,6 +90,7 @@ private: void handleTxError (const QString& error); Connection* conn = nullptr; + QProcess* ezcashd = nullptr; QList* utxos = nullptr; QMap* allBalances = nullptr; From c9dea0fe1551a4ef0dfac88c1284d894f4d5f42a Mon Sep 17 00:00:00 2001 From: adityapk00 Date: Sat, 3 Nov 2018 12:41:52 -0700 Subject: [PATCH 04/23] fix crashes when zcashd is not present --- src/rpc.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/rpc.cpp b/src/rpc.cpp index fa205b9..562a6da 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -213,6 +213,10 @@ void RPC::sendZTransaction(json params, const std::function& cb) { * private keys */ void RPC::getAllPrivKeys(const std::function>)> cb) { + if (conn == nullptr) { + // No connection, just return + return; + } // A special function that will call the callback when two lists have been added auto holder = new QPair>>(); @@ -813,6 +817,12 @@ void RPC::refreshZECPrice() { } void RPC::shutdownZcashd() { + // Shutdown embedded zcashd if it was started + if (ezcashd == nullptr || conn == nullptr) { + // No zcashd running internally, just return + return; + } + json payload = { {"jsonrpc", "1.0"}, {"id", "someid"}, From d5e3af588e19dfb2733c079439f9300acf5a66d0 Mon Sep 17 00:00:00 2001 From: adityapk00 Date: Sat, 3 Nov 2018 15:28:02 -0700 Subject: [PATCH 05/23] start/stop zcashd.exe on windows --- src/connection.cpp | 13 +++++++++++-- src/main.cpp | 1 + src/rpc.cpp | 3 +++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index 159681c..ffca84c 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -146,9 +146,18 @@ bool ConnectionLoader::startEmbeddedZcashd() { // Finally, start zcashd qDebug() << "Starting zcashd"; QFileInfo fi(Settings::getInstance()->getExecName()); - auto zcashdProgram = fi.dir().filePath("zcashd"); +#ifdef Q_OS_LINUX + auto zcashdProgram = "zcashd"; +#elif defined(Q_OS_DARWIN) + auto zcashdProgram = "zcashd"; +#else + auto zcashdProgram = "zcashd.exe"; +#endif + + qDebug() << zcashdProgram << QFile(zcashdProgram).exists(); ezcashd = new QProcess(main); + ezcashd->setWorkingDirectory(fi.dir().absolutePath()); QObject::connect(ezcashd, &QProcess::started, [=] () { qDebug() << "zcashd started"; Settings::getInstance()->setEmbeddedZcashdRunning(true); @@ -160,7 +169,7 @@ bool ConnectionLoader::startEmbeddedZcashd() { }); QObject::connect(ezcashd, &QProcess::errorOccurred, [&] (auto error) mutable { - qDebug() << "Couldn't start zcashd: " << error; + qDebug() << "Couldn't start zcashd: " << error << ezcashd->errorString(); }); ezcashd->start(zcashdProgram); diff --git a/src/main.cpp b/src/main.cpp index 898fc77..da40fa6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,6 +20,7 @@ int main(int argc, char *argv[]) std::srand(std::time(nullptr)); Settings::init(); + Settings::getInstance()->setExecName(argv[0]); if (argc >= 2 && QString::fromStdString(argv[1]) == "-manual") { Settings::getInstance()->setManualConnection(true); diff --git a/src/rpc.cpp b/src/rpc.cpp index 562a6da..de422ac 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -839,6 +839,9 @@ void RPC::shutdownZcashd() { d.setWindowFlags(Qt::SplashScreen); QTimer waiter(main); + + // We capture by reference all the local variables because of the d.exec() + // below, which blocks this function until we exit. QObject::connect(&waiter, &QTimer::timeout, [&] () { if (ezcashd->atEnd()) { qDebug() << "Ended"; From 2b253dd46f85c55dcc4c334bda349ff2b0cd0f11 Mon Sep 17 00:00:00 2001 From: adityapk00 Date: Sun, 4 Nov 2018 20:46:26 -0800 Subject: [PATCH 06/23] prettify loading dialog --- src/connection.cpp | 31 ++++------ src/connection.h | 2 +- src/connection.ui | 121 ++++++++++++++++------------------------ src/fillediconlabel.cpp | 22 ++++++++ src/fillediconlabel.h | 18 ++++++ src/rpc.cpp | 2 +- zec-qt-wallet.pro | 6 +- 7 files changed, 106 insertions(+), 96 deletions(-) create mode 100644 src/fillediconlabel.cpp create mode 100644 src/fillediconlabel.h diff --git a/src/connection.cpp b/src/connection.cpp index ffca84c..15463eb 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -21,7 +21,7 @@ ConnectionLoader::ConnectionLoader(MainWindow* main, RPC* rpc) { int x = (screenGeometry.width() - d->width()) / 2; int y = (screenGeometry.height() - d->height()) / 2; d->move(x, y); - connD->buttonBox->setEnabled(false); + } ConnectionLoader::~ConnectionLoader() { @@ -169,7 +169,7 @@ bool ConnectionLoader::startEmbeddedZcashd() { }); QObject::connect(ezcashd, &QProcess::errorOccurred, [&] (auto error) mutable { - qDebug() << "Couldn't start zcashd: " << error << ezcashd->errorString(); + qDebug() << "Couldn't start zcashd: " << error; }); ezcashd->start(zcashdProgram); @@ -252,18 +252,9 @@ void ConnectionLoader::refreshZcashdState(Connection* connection) { QTimer::singleShot(1000, [=]() { this->refreshZcashdState(connection); }); } else { // Errored out, show error and exit - QString explanation = "Couldn't start zcashd"; + QString explanation = "Couldn't start the embedded zcashd. The process returned:\n\n" % ezcashd->errorString(); this->showError(explanation); } - - // auto isZcashConfFound = connection->config.get()->usingZcashConf; - // QString explanation = QString() - // % (isZcashConfFound ? "A zcash.conf file was found, but a" : "A") - // % " connection to zcashd could not be established.\n\n" - // % "If you are connecting to a remote/non-standard node " - // % "please set the host/port and user/password in the File->Settings menu"; - - // this->showError(explanation); } else if (err == QNetworkReply::NetworkError::AuthenticationRequiredError) { QString explanation = QString() % "Authentication failed. The username / password you specified was " @@ -273,7 +264,7 @@ void ConnectionLoader::refreshZcashdState(Connection* connection) { } else if (err == QNetworkReply::NetworkError::InternalServerError && !res.is_discarded()) { // The server is loading, so just poll until it succeeds QString status = QString::fromStdString(res["error"]["message"]); - showInformation("Your zcashd is starting up. Please wait.\n\n" % status); + showInformation("Your zcashd is starting up. Please wait.", status); // Refresh after one second QTimer::singleShot(1000, [=]() { this->refreshZcashdState(connection); }); @@ -282,18 +273,18 @@ void ConnectionLoader::refreshZcashdState(Connection* connection) { ); } -void ConnectionLoader::showInformation(QString info) { - QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); - connD->icon->setPixmap(icon.pixmap(128, 128)); +void ConnectionLoader::showInformation(QString info, QString detail) { connD->status->setText(info); + connD->statusDetail->setText(detail); } +/** + * Show error will close the loading dialog and show an error. +*/ void ConnectionLoader::showError(QString explanation) { - QIcon icon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical); - connD->icon->setPixmap(icon.pixmap(128, 128)); - connD->status->setText(explanation); + d->close(); - connD->buttonBox->setEnabled(true); + QMessageBox::critical(main, "Error", explanation, QMessageBox::Ok); } QString ConnectionLoader::locateZcashConfFile() { diff --git a/src/connection.h b/src/connection.h index ccdd163..582b3aa 100644 --- a/src/connection.h +++ b/src/connection.h @@ -54,7 +54,7 @@ private: int getProgressFromStatus(QString status); void showError(QString explanation); - void showInformation(QString info); + void showInformation(QString info, QString detail = ""); void doRPCSetConnection(Connection* conn); diff --git a/src/connection.ui b/src/connection.ui index a4d98af..007d877 100644 --- a/src/connection.ui +++ b/src/connection.ui @@ -16,98 +16,75 @@ true - - - - - Qt::Horizontal - - - QDialogButtonBox::Close + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + - - - - TextLabel - - - Qt::AlignCenter - - - 20 - - - - - + + Qt::Horizontal - - - - Qt::Vertical - - - - 20 - 40 - - - - - + Connection Status - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + Qt::AlignCenter true + + + + + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + + + + FilledIconLabel + QLabel +
fillediconlabel.h
+
+
- - - buttonBox - accepted() - ConnectionDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - ConnectionDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - + diff --git a/src/fillediconlabel.cpp b/src/fillediconlabel.cpp new file mode 100644 index 0000000..a04447a --- /dev/null +++ b/src/fillediconlabel.cpp @@ -0,0 +1,22 @@ +#include "fillediconlabel.h" + +FilledIconLabel::FilledIconLabel(QWidget* parent) : + QLabel(parent) { + this->setMinimumSize(1, 1); + setScaledContents(false); +} + + +void FilledIconLabel::resizeEvent(QResizeEvent*) { + // Top pixmap + QIcon icon(":/icons/res/icon.ico"); + QSize sz = size(); + qDebug() << sz; + QPixmap p(sz); + p.fill(Qt::white); + QPainter painter(&p); + painter.drawPixmap((sz.width() - sz.height()) / 2, 0, + icon.pixmap(sz.height(), sz.height())); + + QLabel::setPixmap(p); +} \ No newline at end of file diff --git a/src/fillediconlabel.h b/src/fillediconlabel.h new file mode 100644 index 0000000..a910796 --- /dev/null +++ b/src/fillediconlabel.h @@ -0,0 +1,18 @@ +#ifndef FILLEDICONLABEL_H +#define FILLEDICONLABEL_H + +#include "precompiled.h" + +class FilledIconLabel : public QLabel +{ + Q_OBJECT +public: + explicit FilledIconLabel(QWidget *parent = 0); + +public slots: + void resizeEvent(QResizeEvent *); + +}; + + +#endif // FILLEDICONLABEL_H \ No newline at end of file diff --git a/src/rpc.cpp b/src/rpc.cpp index de422ac..6ef88d5 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -836,7 +836,7 @@ void RPC::shutdownZcashd() { d.setWindowTitle("Waiting for zcashd to exit"); d.setText("Please wait for zcashd to exit. Don't click OK!"); d.setStandardButtons(QMessageBox::NoButton); - d.setWindowFlags(Qt::SplashScreen); + //d.setWindowFlags(Qt::SplashScreen); QTimer waiter(main); diff --git a/zec-qt-wallet.pro b/zec-qt-wallet.pro index 2ece2d0..e7c011e 100644 --- a/zec-qt-wallet.pro +++ b/zec-qt-wallet.pro @@ -53,7 +53,8 @@ SOURCES += \ src/turnstile.cpp \ src/utils.cpp \ src/qrcodelabel.cpp \ - src/connection.cpp + src/connection.cpp \ + src/fillediconlabel.cpp HEADERS += \ src/mainwindow.h \ @@ -71,7 +72,8 @@ HEADERS += \ src/turnstile.h \ src/utils.h \ src/qrcodelabel.h \ - src/connection.h + src/connection.h \ + src/fillediconlabel.h FORMS += \ src/mainwindow.ui \ From 619ff9fdd69a3fe842285bb5378f8740b41856d3 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Mon, 5 Nov 2018 21:19:08 -0800 Subject: [PATCH 07/23] Download Params --- src/connection.cpp | 155 +++++++++++++++++++++++++++++++++------------ src/connection.h | 10 +++ src/precompiled.h | 1 + src/rpc.cpp | 3 +- 4 files changed, 125 insertions(+), 44 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index f7a0a52..8731d56 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -81,56 +81,111 @@ void ConnectionLoader::createZcashConf() { // Fetch params. { - QFileInfo fi(Settings::getInstance()->getExecName()); - auto fetchParamsProgram = fi.dir().filePath("zcash-fetch-params"); + downloadParams([=] () { + startEmbeddedZcashd(); - QProcess* p = new QProcess(main); - QObject::connect(p, &QProcess::readyReadStandardOutput, [=] () { - qDebug() << "stdout:" << p->readAllStandardOutput(); - }); - QObject::connect(p, QOverload::of(&QProcess::finished), - [=](int exitCode, QProcess::ExitStatus exitStatus) { - qDebug() << "finished with code " << exitCode; - p->deleteLater(); - }); - p->start(fetchParamsProgram); + auto config = autoDetectZcashConf(); + if (config.get() != nullptr) { + auto connection = makeConnection(config); + refreshZcashdState(connection); - // stdout: "Zcash - fetch-params.sh\n\nThis script will fetch the Zcash zkSNARK parameters and verify their\nintegrity with sha256sum.\n\nIf they already exist locally, it will exit now and do nothing else.\nThe parameters are currently just under 911MB in size, so plan accordingly\nfor your bandwidth constraints. If the files are already present and\nhave the correct sha256sum, no networking is used.\n\nCreating params directory. For details about this directory, see:\n/home/adityapk/.zcash-params/README\n\n\nRetrieving (wget): https://z.cash/downloads/sprout-proving.key\n" - // stdout: "Download successful!\n" - // stdout: "/home/adityapk/.zcash-params/sprout-proving.key.dl: OK\n" - // stdout: "renamed '/home/adityapk/.zcash-params/sprout-proving.key.dl' -> '/home/adityapk/.zcash-params/sprout-proving.key'\n" - // stdout: "\nRetrieving (wget): https://z.cash/downloads/sprout-verifying.key\n" - // stdout: "Download successful!\n" - // stdout: "/home/adityapk/.zcash-params/sprout-verifying.key.dl: OK\n" - // stdout: "renamed '/home/adityapk/.zcash-params/sprout-verifying.key.dl' -> '/home/adityapk/.zcash-params/sprout-verifying.key'\n" - // stdout: "\nRetrieving (wget): https://z.cash/downloads/sapling-spend.params\n" - // stdout: "Download successful!\n" - // stdout: "/home/adityapk/.zcash-params/sapling-spend.params.dl: OK\n" - // stdout: "renamed '/home/adityapk/.zcash-params/sapling-spend.params.dl' -> '/home/adityapk/.zcash-params/sapling-spend.params'\n" - // stdout: "\nRetrieving (wget): https://z.cash/downloads/sapling-output.params\n" - // stdout: "Download successful!\n" - // stdout: "/home/adityapk/.zcash-params/sapling-output.params.dl: OK\n" - // stdout: "renamed '/home/adityapk/.zcash-params/sapling-output.params.dl' -> '/home/adityapk/.zcash-params/sapling-output.params'\n" - // stdout: "\nRetrieving (wget): https://z.cash/downloads/sprout-groth16.params\n" - // stdout: "Download successful!\n" - // stdout: "/home/adityapk/.zcash-params/sprout-groth16.params.dl: OK\n" - // stdout: "renamed '/home/adityapk/.zcash-params/sprout-groth16.params.dl' -> '/home/adityapk/.zcash-params/sprout-groth16.params'\n" - // finished with code 0 + return; + } else { + qDebug() << "Coulnd't get embedded startup zcashd"; + } + }); + } +} + +void ConnectionLoader::downloadParams(std::function cb) { + // Add all the files to the download queue + downloadQueue = new QQueue(); + client = new QNetworkAccessManager(main); + + downloadQueue->enqueue(QUrl("https://z.cash/downloads/sapling-output.params")); + downloadQueue->enqueue(QUrl("https://z.cash/downloads/sapling-spend.params")); + downloadQueue->enqueue(QUrl("https://z.cash/downloads/sprout-proving.key")); + downloadQueue->enqueue(QUrl("https://z.cash/downloads/sprout-verifying.key")); + downloadQueue->enqueue(QUrl("https://z.cash/downloads/sprout-groth16.params")); + + doNextDownload(cb); + + d->show(); +} + +void ConnectionLoader::doNextDownload(std::function cb) { + qDebug() << "Attempting download"; + + auto fnSaveFileName = [&] (QUrl url) { + QString path = url.path(); + QString basename = QFileInfo(path).fileName(); + + return basename; + }; + + if (downloadQueue->isEmpty()) { + delete downloadQueue; + client->deleteLater(); + + this->showInformation("All Downloads Finished Successfully!"); + cb(); + return; } - { - startEmbeddedZcashd(); + QUrl url = downloadQueue->dequeue(); + int filesRemaining = downloadQueue->size(); - auto config = autoDetectZcashConf(); - if (config.get() != nullptr) { - auto connection = makeConnection(config); - refreshZcashdState(connection); + QString filename = fnSaveFileName(url); + QString paramsDir = zcashParamsDir(); + currentOutput = new QFile(QDir(paramsDir).filePath(filename)); - return; + if (!currentOutput->open(QIODevice::WriteOnly)) { + this->showError("Couldn't download params. Please check the help site for more info."); + } + qDebug() << "Downloading " << url << " to " << filename; + + QNetworkRequest request(url); + request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + currentDownload = client->get(request); + downloadTime.start(); + + // Download Progress + QObject::connect(currentDownload, &QNetworkReply::downloadProgress, [=] (auto done, auto total) { + // calculate the download speed + double speed = done * 1000.0 / downloadTime.elapsed(); + QString unit; + if (speed < 1024) { + unit = "bytes/sec"; + } else if (speed < 1024*1024) { + speed /= 1024; + unit = "kB/s"; } else { - qDebug() << "Coulnd't get embedded startup zcashd"; + speed /= 1024*1024; + unit = "MB/s"; } - } + + this->showInformation( + "Downloading " % filename % (filesRemaining > 1 ? " ( +" % QString::number(filesRemaining) % " more remaining )" : QString("")), + QString::number(done/1024/1024, 'f', 0) % "MB of " % QString::number(total/1024/1024, 'f', 0) + "MB at " % QString::number(speed, 'f', 2) % unit); + }); + + // Download Finished + QObject::connect(currentDownload, &QNetworkReply::finished, [=] () { + currentOutput->close(); + currentDownload->deleteLater(); + currentOutput->deleteLater(); + + if (currentDownload->error()) { + this->showError("Downloading " + filename + " failed/ Please check the help site for more info"); + } else { + doNextDownload(cb); + } + }); + + // Download new data available. + QObject::connect(currentDownload, &QNetworkReply::readyRead, [=] () { + currentOutput->write(currentDownload->readAll()); + }); } bool ConnectionLoader::startEmbeddedZcashd() { @@ -310,6 +365,22 @@ QString ConnectionLoader::zcashConfWritableLocation() { return confLocation; } +QString ConnectionLoader::zcashParamsDir() { + #ifdef Q_OS_LINUX + auto paramsLocation = QDir(QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath(".zcash-params")); +#elif defined(Q_OS_DARWIN) + //auto paramsLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath("/Library/Application Support/Zcash/zcash.conf"); +#else + auto paramsLocation = QDir(QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("../../ZcashParams")); +#endif + + if (!paramsLocation.exists()) { + QDir().mkpath(paramsLocation.absolutePath()); + } + + return paramsLocation.absolutePath(); +} + /** * Try to automatically detect a zcash.conf file in the correct location and load parameters */ diff --git a/src/connection.h b/src/connection.h index 582b3aa..384dd5c 100644 --- a/src/connection.h +++ b/src/connection.h @@ -47,7 +47,10 @@ private: void createZcashConf(); QString locateZcashConfFile(); QString zcashConfWritableLocation(); + QString zcashParamsDir(); + void downloadParams(std::function cb); + void doNextDownload(std::function cb); bool startEmbeddedZcashd(); void refreshZcashdState(Connection* connection); @@ -65,6 +68,13 @@ private: MainWindow* main; RPC* rpc; + + QNetworkReply* currentDownload = nullptr; + QFile* currentOutput = nullptr; + QQueue* downloadQueue = nullptr; + + QNetworkAccessManager* client = nullptr; + QTime downloadTime; }; /** diff --git a/src/precompiled.h b/src/precompiled.h index 4663c74..e046d7e 100644 --- a/src/precompiled.h +++ b/src/precompiled.h @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include diff --git a/src/rpc.cpp b/src/rpc.cpp index 1133359..4155828 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -836,8 +836,7 @@ void RPC::shutdownZcashd() { d.setWindowTitle("Waiting for zcashd to exit"); d.setText("Please wait for zcashd to exit. Don't click OK!"); d.setStandardButtons(QMessageBox::NoButton); - //d.setWindowFlags(Qt::SplashScreen); - + QTimer waiter(main); // We capture by reference all the local variables because of the d.exec() From a2f6768f6ca347e44c086c6e94f1d3398b8ad6be Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Tue, 6 Nov 2018 13:47:23 -0800 Subject: [PATCH 08/23] Skip existing files --- src/connection.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/connection.cpp b/src/connection.cpp index 8731d56..f692ca2 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -139,6 +139,11 @@ void ConnectionLoader::doNextDownload(std::function cb) { QString paramsDir = zcashParamsDir(); currentOutput = new QFile(QDir(paramsDir).filePath(filename)); + if (currentOutput->exists()) { + qDebug() << filename << " already exists, skipping "; + doNextDownload(cb); + } + if (!currentOutput->open(QIODevice::WriteOnly)) { this->showError("Couldn't download params. Please check the help site for more info."); } From 5fc905c9266ba05d2c7cf7331740d62b16028529 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Tue, 6 Nov 2018 15:00:10 -0800 Subject: [PATCH 09/23] zcashd pane on main tab widget --- application.qrc | 5 +- res/zcashdlogo.gif | Bin 0 -> 4270 bytes src/connection.cpp | 1 + src/fillediconlabel.cpp | 15 ++-- src/fillediconlabel.h | 3 + src/mainwindow.cpp | 5 ++ src/mainwindow.h | 1 + src/mainwindow.ui | 156 ++++++++++++++++++++++++++++++++++++++-- src/rpc.cpp | 22 ++++++ src/rpc.h | 1 + 10 files changed, 196 insertions(+), 13 deletions(-) create mode 100644 res/zcashdlogo.gif diff --git a/application.qrc b/application.qrc index 1b2fcc7..29f23df 100644 --- a/application.qrc +++ b/application.qrc @@ -6,5 +6,8 @@ res/connected.png res/loading.gif res/icon.ico - + + + res/zcashdlogo.gif + diff --git a/res/zcashdlogo.gif b/res/zcashdlogo.gif new file mode 100644 index 0000000000000000000000000000000000000000..431e4fc20e56a09c10731e78387a5b09e3668634 GIT binary patch literal 4270 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 Q+`=$?y&oLIH4y;-JJ8X46aWAK literal 0 HcmV?d00001 diff --git a/src/connection.cpp b/src/connection.cpp index f692ca2..40d61bf 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -15,6 +15,7 @@ ConnectionLoader::ConnectionLoader(MainWindow* main, RPC* rpc) { d = new QDialog(main); connD = new Ui_ConnectionDialog(); connD->setupUi(d); + connD->topIcon->setBasePixmap(QIcon(":/icons/res/icon.ico").pixmap(256, 256)); // Center on screen QRect screenGeometry = QApplication::desktop()->screenGeometry(d); diff --git a/src/fillediconlabel.cpp b/src/fillediconlabel.cpp index a04447a..9b5d9cf 100644 --- a/src/fillediconlabel.cpp +++ b/src/fillediconlabel.cpp @@ -6,17 +6,20 @@ FilledIconLabel::FilledIconLabel(QWidget* parent) : setScaledContents(false); } +void FilledIconLabel::setBasePixmap(QPixmap pm) { + basePm = pm; +} void FilledIconLabel::resizeEvent(QResizeEvent*) { - // Top pixmap - QIcon icon(":/icons/res/icon.ico"); - QSize sz = size(); - qDebug() << sz; + // Top pixmap + QSize sz = size(); + + QPixmap scaled = basePm.scaled(sz, Qt::KeepAspectRatio, Qt::SmoothTransformation); + QPixmap p(sz); p.fill(Qt::white); QPainter painter(&p); - painter.drawPixmap((sz.width() - sz.height()) / 2, 0, - icon.pixmap(sz.height(), sz.height())); + painter.drawPixmap((sz.width() - scaled.width()) / 2, (sz.height() - scaled.height()) / 2, scaled); QLabel::setPixmap(p); } \ No newline at end of file diff --git a/src/fillediconlabel.h b/src/fillediconlabel.h index a910796..d5de800 100644 --- a/src/fillediconlabel.h +++ b/src/fillediconlabel.h @@ -8,10 +8,13 @@ class FilledIconLabel : public QLabel Q_OBJECT public: explicit FilledIconLabel(QWidget *parent = 0); + void setBasePixmap(QPixmap pm); public slots: void resizeEvent(QResizeEvent *); +private: + QPixmap basePm; }; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2e92c10..fd489dd 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -75,6 +75,7 @@ MainWindow::MainWindow(QWidget *parent) : setupRecieveTab(); setupBalancesTab(); setupTurnstileDialog(); + setupZcashdTab(); rpc = new RPC(this); @@ -700,6 +701,10 @@ void MainWindow::setupBalancesTab() { }); } +void MainWindow::setupZcashdTab() { + ui->zcashdlogo->setBasePixmap(QPixmap(":/img/res/zcashdlogo.gif")); +} + void MainWindow::setupTransactionsTab() { // Set up context menu on transactions tab ui->transactionsTable->setContextMenuPolicy(Qt::CustomContextMenu); diff --git a/src/mainwindow.h b/src/mainwindow.h index 4f5005c..e634a37 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -49,6 +49,7 @@ private: void setupTransactionsTab(); void setupRecieveTab(); void setupBalancesTab(); + void setupZcashdTab(); void setupTurnstileDialog(); void setupSettingsModal(); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 838cd52..4f22232 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 889 - 603 + 968 + 616 @@ -22,7 +22,7 @@ - 1 + 4 @@ -316,8 +316,8 @@ 0 0 - 841 - 321 + 920 + 334 @@ -715,6 +715,145 @@
+ + + zcashd + + + + + + + + + 0 + 0 + + + + + + + false + + + + + + + + + + + + + You are currently not mining + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + TextLabel + + + + + + + Block Height + + + + + + + TextLabel + + + + + + + Network Solution Rate + + + + + + + Connections + + + + + + + TextLabel + + + + + + + Qt::Horizontal + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + | + + + + + + + | + + + + + + + | + + + + + + + + + + @@ -724,7 +863,7 @@ 0 0 - 889 + 968 22 @@ -835,6 +974,11 @@ QLabel
qrcodelabel.h
+ + FilledIconLabel + QLabel +
fillediconlabel.h
+
tabWidget diff --git a/src/rpc.cpp b/src/rpc.cpp index 4155828..022fba1 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -477,6 +477,28 @@ void RPC::getInfoThenRefresh(bool force) { refreshTransactions(); } + // Get network sol/s + if (ezcashd != nullptr) { + int conns = reply["connections"].get(); + + json payload = { + {"jsonrpc", "1.0"}, + {"id", "someid"}, + {"method", "getnetworksolps"} + }; + + conn->doRPCIgnoreError(payload, [=](const json& reply) { + qint64 solrate = reply.get(); + + ui->blockheight->setText(QString::number(curBlock)); + ui->numconnections->setText(QString::number(conns)); + ui->solrate->setText(QString::number(solrate) % " Sol/s"); + }); + } else { + ui->tabWidget->removeTab(4); + } + + // Call to see if the blockchain is syncing. json payload = { {"jsonrpc", "1.0"}, diff --git a/src/rpc.h b/src/rpc.h index 3ededd6..c2539c3 100644 --- a/src/rpc.h +++ b/src/rpc.h @@ -33,6 +33,7 @@ public: void setConnection(Connection* c); void setEZcashd(QProcess* p); + const QProcess* getEZcashD() { return ezcashd; } void refresh(bool force = false); From 02e1a2de36b73eaa01fc3ae78778f2f846b94acc Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Tue, 6 Nov 2018 15:17:55 -0800 Subject: [PATCH 10/23] small fixes --- src/fillediconlabel.cpp | 6 ++++-- src/mainwindow.ui | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/fillediconlabel.cpp b/src/fillediconlabel.cpp index 9b5d9cf..0982cab 100644 --- a/src/fillediconlabel.cpp +++ b/src/fillediconlabel.cpp @@ -10,8 +10,10 @@ void FilledIconLabel::setBasePixmap(QPixmap pm) { basePm = pm; } -void FilledIconLabel::resizeEvent(QResizeEvent*) { - // Top pixmap +/** + * When resized, we re-draw the whole pixmap, resizing it as needed. + */ +void FilledIconLabel::resizeEvent(QResizeEvent*) { QSize sz = size(); QPixmap scaled = basePm.scaled(sz, Qt::KeepAspectRatio, Qt::SmoothTransformation); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 4f22232..3fc26f4 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -774,7 +774,7 @@ - Block Height + Block height @@ -788,7 +788,7 @@ - Network Solution Rate + Network solution rate From 2b9cc055bf1c7eb0b12d8021343400a83007831d Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Wed, 7 Nov 2018 14:54:31 -0800 Subject: [PATCH 11/23] Popup splash screen properly --- src/connection.cpp | 32 +++++++++++--------------------- src/connection.h | 1 - src/connection.ui | 3 +++ src/main.cpp | 2 +- 4 files changed, 15 insertions(+), 23 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index 40d61bf..b9ec551 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -25,21 +25,13 @@ ConnectionLoader::ConnectionLoader(MainWindow* main, RPC* rpc) { } -ConnectionLoader::~ConnectionLoader() { +ConnectionLoader::~ConnectionLoader() { delete d; delete connD; } -void ConnectionLoader::loadConnection() { - // Load from settings if it is a manual connection. - if (Settings::getInstance()->getIsManualConnection()) { - doManualConnect(); - } else { - doAutoConnect(); - } -} - -void ConnectionLoader::doAutoConnect() { +void ConnectionLoader::loadConnection() { + d->show(); // Priority 1: Try to connect to detect zcash.conf and connect to it. auto config = autoDetectZcashConf(); @@ -48,9 +40,11 @@ void ConnectionLoader::doAutoConnect() { refreshZcashdState(connection); return; - } else { + } else if (!Settings::getInstance()->getIsManualConnection()){ // zcash.conf was not found, so create one createZcashConf(); + } else { + doManualConnect(); } } @@ -109,9 +103,7 @@ void ConnectionLoader::downloadParams(std::function cb) { downloadQueue->enqueue(QUrl("https://z.cash/downloads/sprout-verifying.key")); downloadQueue->enqueue(QUrl("https://z.cash/downloads/sprout-groth16.params")); - doNextDownload(cb); - - d->show(); + doNextDownload(cb); } void ConnectionLoader::doNextDownload(std::function cb) { @@ -242,7 +234,6 @@ void ConnectionLoader::doManualConnect() { auto config = loadFromSettings(); if (config.get() == nullptr) { - d->show(); // Nothing configured, show an error QString explanation = QString() % "A manual connection was requested, but the settings are not configured.\n\n" @@ -299,8 +290,6 @@ void ConnectionLoader::refreshZcashdState(Connection* connection) { this->doRPCSetConnection(connection); }, [=] (auto reply, auto res) { - d->show(); - auto err = reply->error(); // Failed, see what it is. //qDebug() << err << ":" << QString::fromStdString(res.dump()); @@ -323,6 +312,8 @@ void ConnectionLoader::refreshZcashdState(Connection* connection) { this->showError(explanation); } else if (err == QNetworkReply::NetworkError::InternalServerError && !res.is_discarded()) { + d->show(); + // The server is loading, so just poll until it succeeds QString status = QString::fromStdString(res["error"]["message"]); showInformation("Your zcashd is starting up. Please wait.", status); @@ -343,9 +334,8 @@ void ConnectionLoader::showInformation(QString info, QString detail) { * Show error will close the loading dialog and show an error. */ void ConnectionLoader::showError(QString explanation) { - d->close(); - - QMessageBox::critical(main, "Error", explanation, QMessageBox::Ok); + d->hide(); + QMessageBox::critical(main, "Connection Error", explanation, QMessageBox::Ok); } QString ConnectionLoader::locateZcashConfFile() { diff --git a/src/connection.h b/src/connection.h index 384dd5c..6c05ced 100644 --- a/src/connection.h +++ b/src/connection.h @@ -41,7 +41,6 @@ private: Connection* makeConnection(std::shared_ptr config); - void doAutoConnect(); void doManualConnect(); void createZcashConf(); diff --git a/src/connection.ui b/src/connection.ui index 007d877..704f9d9 100644 --- a/src/connection.ui +++ b/src/connection.ui @@ -2,6 +2,9 @@ ConnectionDialog + + Qt::ApplicationModal + 0 diff --git a/src/main.cpp b/src/main.cpp index da40fa6..5eb849b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -22,7 +22,7 @@ int main(int argc, char *argv[]) Settings::init(); Settings::getInstance()->setExecName(argv[0]); - if (argc >= 2 && QString::fromStdString(argv[1]) == "-manual") { + if (argc >= 2 && QString::fromStdString(argv[1]) == "--no-embedded") { Settings::getInstance()->setManualConnection(true); } From 0f603f0d0f3a2d375283c6a9a38278c6f19419c9 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Wed, 7 Nov 2018 15:50:35 -0800 Subject: [PATCH 12/23] Clean up connection code --- src/connection.cpp | 98 ++++++++++++++++++++++++++-------------------- src/connection.h | 2 +- src/main.cpp | 4 +- src/rpc.cpp | 5 +++ src/settings.h | 10 ++--- 5 files changed, 67 insertions(+), 52 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index b9ec551..7b4be73 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -37,15 +37,37 @@ void ConnectionLoader::loadConnection() { if (config.get() != nullptr) { auto connection = makeConnection(config); - refreshZcashdState(connection); - return; - } else if (!Settings::getInstance()->getIsManualConnection()){ - // zcash.conf was not found, so create one - createZcashConf(); + refreshZcashdState(connection, [=] () { + // Refused connection. So try and start embedded zcashd + if (Settings::getInstance()->useEmbedded()) { + this->showInformation("Starting Embedded zcashd"); + if (this->startEmbeddedZcashd()) { + // Embedded zcashd started up. Wait a second and then refresh the connection + QTimer::singleShot(1000, [=]() { loadConnection(); } ); + } else { + // Errored out, show error and exit + QString explanation = QString() % "Couldn't start the embedded zcashd.\n\n" % + "This is most likely because of corrupt zcash-params. Please delete your zcash-params directory and restart.\n\n" % + (ezcashd ? "The process returned:\n\n" % ezcashd->errorString() : QString("")); + this->showError(explanation); + } + } else { + // zcash.conf exists, there's no connection, and the user asked us not to start zcashd. Error! + QString explanation = QString() % "Couldn't connect to zcashd configured in zcash.conf.\n\n" % + "Not starting embedded zcashd because --no-embedded was passed"; + this->showError(explanation); + } + }); } else { - doManualConnect(); - } + if (Settings::getInstance()->useEmbedded()) { + // zcash.conf was not found, so create one + createZcashConf(); + } else { + // Fall back to manual connect + doManualConnect(); + } + } } /** @@ -74,22 +96,8 @@ void ConnectionLoader::createZcashConf() { file.close(); } - // Fetch params. - { - downloadParams([=] () { - startEmbeddedZcashd(); - - auto config = autoDetectZcashConf(); - if (config.get() != nullptr) { - auto connection = makeConnection(config); - refreshZcashdState(connection); - - return; - } else { - qDebug() << "Coulnd't get embedded startup zcashd"; - } - }); - } + // Fetch params. After params are fetched, try loading the connection again + downloadParams([=] () { this->loadConnection(); }); } void ConnectionLoader::downloadParams(std::function cb) { @@ -135,6 +143,8 @@ void ConnectionLoader::doNextDownload(std::function cb) { if (currentOutput->exists()) { qDebug() << filename << " already exists, skipping "; doNextDownload(cb); + + return; } if (!currentOutput->open(QIODevice::WriteOnly)) { @@ -187,6 +197,9 @@ void ConnectionLoader::doNextDownload(std::function cb) { } bool ConnectionLoader::startEmbeddedZcashd() { + if (!Settings::getInstance()->useEmbedded()) + return false; + if (ezcashd != nullptr) { if (ezcashd->state() == QProcess::NotRunning) { qDebug() << "Process started and then crashed"; @@ -213,7 +226,6 @@ bool ConnectionLoader::startEmbeddedZcashd() { ezcashd->setWorkingDirectory(fi.dir().absolutePath()); QObject::connect(ezcashd, &QProcess::started, [=] () { qDebug() << "zcashd started"; - Settings::getInstance()->setEmbeddedZcashdRunning(true); }); QObject::connect(ezcashd, QOverload::of(&QProcess::finished), @@ -237,7 +249,7 @@ void ConnectionLoader::doManualConnect() { // Nothing configured, show an error QString explanation = QString() % "A manual connection was requested, but the settings are not configured.\n\n" - % "Please set the host/port and user/password in the File->Settings menu."; + % "Please set the host/port and user/password in the Edit->Settings menu."; showError(explanation); doRPCSetConnection(nullptr); @@ -246,7 +258,16 @@ void ConnectionLoader::doManualConnect() { } auto connection = makeConnection(config); - refreshZcashdState(connection); + refreshZcashdState(connection, [=] () { + QString explanation = QString() + % "Could not connect to zcashd configured in settings.\n\n" + % "Please set the host/port and user/password in the Edit->Settings menu."; + + showError(explanation); + doRPCSetConnection(nullptr); + + return; + }); } void ConnectionLoader::doRPCSetConnection(Connection* conn) { @@ -277,7 +298,7 @@ Connection* ConnectionLoader::makeConnection(std::shared_ptr c return new Connection(main, client, request, config); } -void ConnectionLoader::refreshZcashdState(Connection* connection) { +void ConnectionLoader::refreshZcashdState(Connection* connection, std::function refused) { json payload = { {"jsonrpc", "1.0"}, {"id", "someid"}, @@ -289,37 +310,27 @@ void ConnectionLoader::refreshZcashdState(Connection* connection) { d->hide(); this->doRPCSetConnection(connection); }, - [=] (auto reply, auto res) { - auto err = reply->error(); + [=] (auto reply, auto res) { // Failed, see what it is. + auto err = reply->error(); //qDebug() << err << ":" << QString::fromStdString(res.dump()); if (err == QNetworkReply::NetworkError::ConnectionRefusedError) { - // Start embedded zcasd - this->showInformation("Starting Embedded zcashd"); - if (this->startEmbeddedZcashd()) { - // Refresh after one second - QTimer::singleShot(1000, [=]() { this->refreshZcashdState(connection); }); - } else { - // Errored out, show error and exit - QString explanation = "Couldn't start the embedded zcashd. The process returned:\n\n" % ezcashd->errorString(); - this->showError(explanation); - } + refused(); } else if (err == QNetworkReply::NetworkError::AuthenticationRequiredError) { QString explanation = QString() % "Authentication failed. The username / password you specified was " % "not accepted by zcashd. Try changing it in the Edit->Settings menu"; this->showError(explanation); - } else if (err == QNetworkReply::NetworkError::InternalServerError && !res.is_discarded()) { - d->show(); - + } else if (err == QNetworkReply::NetworkError::InternalServerError && + !res.is_discarded()) { // The server is loading, so just poll until it succeeds QString status = QString::fromStdString(res["error"]["message"]); showInformation("Your zcashd is starting up. Please wait.", status); // Refresh after one second - QTimer::singleShot(1000, [=]() { this->refreshZcashdState(connection); }); + QTimer::singleShot(1000, [=]() { this->refreshZcashdState(connection, refused); }); } } ); @@ -335,6 +346,7 @@ void ConnectionLoader::showInformation(QString info, QString detail) { */ void ConnectionLoader::showError(QString explanation) { d->hide(); + main->ui->statusBar->showMessage("Connection Error"); QMessageBox::critical(main, "Connection Error", explanation, QMessageBox::Ok); } diff --git a/src/connection.h b/src/connection.h index 6c05ced..fc3c3c0 100644 --- a/src/connection.h +++ b/src/connection.h @@ -52,7 +52,7 @@ private: void doNextDownload(std::function cb); bool startEmbeddedZcashd(); - void refreshZcashdState(Connection* connection); + void refreshZcashdState(Connection* connection, std::function refused); int getProgressFromStatus(QString status); void showError(QString explanation); diff --git a/src/main.cpp b/src/main.cpp index 5eb849b..791a4bd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,7 +23,9 @@ int main(int argc, char *argv[]) Settings::getInstance()->setExecName(argv[0]); if (argc >= 2 && QString::fromStdString(argv[1]) == "--no-embedded") { - Settings::getInstance()->setManualConnection(true); + Settings::getInstance()->setUseEmbedded(false); + } else { + Settings::getInstance()->setUseEmbedded(true); } QCoreApplication::setOrganizationName("zec-qt-wallet-org"); diff --git a/src/rpc.cpp b/src/rpc.cpp index 022fba1..da02c53 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -8,6 +8,8 @@ using json = nlohmann::json; RPC::RPC(MainWindow* main) { auto cl = new ConnectionLoader(main, this); + + // Show a default no connection message until we can connect. cl->loadConnection(); this->main = main; @@ -72,6 +74,8 @@ void RPC::setConnection(Connection* c) { delete conn; this->conn = c; + ui->statusBar->showMessage("Ready!"); + refreshZECPrice(); refresh(); } @@ -495,6 +499,7 @@ void RPC::getInfoThenRefresh(bool force) { ui->solrate->setText(QString::number(solrate) % " Sol/s"); }); } else { + qDebug() << "removing tab!"; ui->tabWidget->removeTab(4); } diff --git a/src/settings.h b/src/settings.h index de7ebb8..a19d9fe 100644 --- a/src/settings.h +++ b/src/settings.h @@ -29,14 +29,11 @@ public: bool isSyncing(); void setSyncing(bool syncing); - bool getIsManualConnection() { return _manualConn; } - void setManualConnection(bool manual) {_manualConn = manual;} - QString getExecName() { return _executable; } void setExecName(QString name) { _executable = name; } - void setEmbeddedZcashdRunning(bool r) { _isEmbeddedZcashd = r; } - bool isEmbeddedZcashdRunning() { return _isEmbeddedZcashd; } + void setUseEmbedded(bool r) { _useEmbedded = r; } + bool useEmbedded() { return _useEmbedded; } int getBlockNumber(); void setBlockNumber(int number); @@ -69,8 +66,7 @@ private: bool _isTestnet = false; bool _isSyncing = false; int _blockNumber = 0; - bool _manualConn = false; - bool _isEmbeddedZcashd = false; + bool _useEmbedded = false; double zecPrice = 0.0; }; From f485e0fa1fc4c182f8e75ad97bf5cdc8deff0ba2 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Wed, 7 Nov 2018 21:11:53 -0800 Subject: [PATCH 13/23] Proper shutdown procedure --- src/connection.cpp | 16 ++++++++++++++++ src/connection.h | 5 +++++ src/rpc.cpp | 9 ++++++--- src/rpc.h | 1 + 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index 7b4be73..42ff779 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -487,10 +487,19 @@ Connection::~Connection() { void Connection::doRPC(const json& payload, const std::function& cb, const std::function& ne) { + if (shutdownInProgress) { + qDebug() << "Ignoring RPC because shutdown in progress"; + return; + } + QNetworkReply *reply = restclient->post(*request, QByteArray::fromStdString(payload.dump())); QObject::connect(reply, &QNetworkReply::finished, [=] { reply->deleteLater(); + if (shutdownInProgress) { + qDebug() << "Ignoring callback because shutdown in progress"; + return; + } if (reply->error() != QNetworkReply::NoError) { auto parsed = json::parse(reply->readAll(), nullptr, false); @@ -530,3 +539,10 @@ void Connection::showTxError(const QString& error) { QMessageBox::critical(main, "Transaction Error", "There was an error sending the transaction. The error was: \n\n" + error, QMessageBox::StandardButton::Ok); } + +/** + * Prevent all future calls from going through + */ +void Connection::shutdown() { + shutdownInProgress = true; +} \ No newline at end of file diff --git a/src/connection.h b/src/connection.h index fc3c3c0..95e157f 100644 --- a/src/connection.h +++ b/src/connection.h @@ -90,6 +90,8 @@ public: std::shared_ptr config; MainWindow* main; + void shutdown(); + void doRPC(const json& payload, const std::function& cb, const std::function& ne); void doRPCWithDefaultErrorHandling(const json& payload, const std::function& cb); @@ -143,6 +145,9 @@ public: }); waitTimer->start(100); } + +private: + bool shutdownInProgress = false; }; #endif diff --git a/src/rpc.cpp b/src/rpc.cpp index da02c53..db5da25 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -857,6 +857,8 @@ void RPC::shutdownZcashd() { }; conn->doRPCWithDefaultErrorHandling(payload, [=](auto) {}); + conn->shutdown(); + QMessageBox d(main); d.setIcon(QMessageBox::Icon::Information); @@ -869,11 +871,12 @@ void RPC::shutdownZcashd() { // We capture by reference all the local variables because of the d.exec() // below, which blocks this function until we exit. QObject::connect(&waiter, &QTimer::timeout, [&] () { - if (ezcashd->atEnd()) { + if (ezcashd->atEnd() && ezcashd->processId() == 0) { qDebug() << "Ended"; - d.accept(); + waiter.stop(); + QTimer::singleShot(1000, [&]() { d.accept(); }); } else { - qDebug() << "Not ended"; + qDebug() << "Not ended, continuing to wait..."; } }); waiter.start(1000); diff --git a/src/rpc.h b/src/rpc.h index c2539c3..6d2d8e9 100644 --- a/src/rpc.h +++ b/src/rpc.h @@ -112,6 +112,7 @@ private: // Current balance in the UI. If this number updates, then refresh the UI QString currentBalance; + // First time warning flag for no connection bool firstTime = true; }; From cfeec8be9ea3b80d1dfe8363045b4366f5131f19 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Wed, 7 Nov 2018 21:20:50 -0800 Subject: [PATCH 14/23] cleanup logo --- res/zcashdlogo.gif | Bin 4270 -> 4209 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/res/zcashdlogo.gif b/res/zcashdlogo.gif index 431e4fc20e56a09c10731e78387a5b09e3668634..bde1631e8c11874fee32a2df38fde78ffb0662f2 100644 GIT binary patch delta 3505 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 From d2c103f032a397dbdabfac1bc427a82ec4674864 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Wed, 7 Nov 2018 21:37:42 -0800 Subject: [PATCH 15/23] Safe download --- src/connection.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index 42ff779..f9af50c 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -48,7 +48,7 @@ void ConnectionLoader::loadConnection() { } else { // Errored out, show error and exit QString explanation = QString() % "Couldn't start the embedded zcashd.\n\n" % - "This is most likely because of corrupt zcash-params. Please delete your zcash-params directory and restart.\n\n" % + "Maybe the zcash-params are corrupt? Please delete your zcash-params directory and restart.\n\n" % (ezcashd ? "The process returned:\n\n" % ezcashd->errorString() : QString("")); this->showError(explanation); } @@ -115,8 +115,6 @@ void ConnectionLoader::downloadParams(std::function cb) { } void ConnectionLoader::doNextDownload(std::function cb) { - qDebug() << "Attempting download"; - auto fnSaveFileName = [&] (QUrl url) { QString path = url.path(); QString basename = QFileInfo(path).fileName(); @@ -138,15 +136,17 @@ void ConnectionLoader::doNextDownload(std::function cb) { QString filename = fnSaveFileName(url); QString paramsDir = zcashParamsDir(); - currentOutput = new QFile(QDir(paramsDir).filePath(filename)); - if (currentOutput->exists()) { + if (QFile(QDir(paramsDir).filePath(filename)).exists()) { qDebug() << filename << " already exists, skipping "; doNextDownload(cb); return; } + // The downloaded file is written to a new name, and then renamed when the operation completes. + currentOutput = new QFile(QDir(paramsDir).filePath(filename + ".part")); + if (!currentOutput->open(QIODevice::WriteOnly)) { this->showError("Couldn't download params. Please check the help site for more info."); } @@ -179,6 +179,9 @@ void ConnectionLoader::doNextDownload(std::function cb) { // Download Finished QObject::connect(currentDownload, &QNetworkReply::finished, [=] () { + // Rename file + currentOutput->rename(QDir(paramsDir).filePath(filename)); + currentOutput->close(); currentDownload->deleteLater(); currentOutput->deleteLater(); @@ -220,7 +223,10 @@ bool ConnectionLoader::startEmbeddedZcashd() { auto zcashdProgram = "zcashd.exe"; #endif - qDebug() << zcashdProgram << QFile(zcashdProgram).exists(); + if (!QFile(zcashdProgram).exists()) { + qDebug() << "Can't find zcashd"; + return false; + } ezcashd = new QProcess(main); ezcashd->setWorkingDirectory(fi.dir().absolutePath()); From b2fa525987455ff311b72bf7d7278b4ec0493efb Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Wed, 7 Nov 2018 21:40:57 -0800 Subject: [PATCH 16/23] Download params before creating zcash.conf --- src/connection.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index f9af50c..231ed93 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -74,8 +74,9 @@ void ConnectionLoader::loadConnection() { * This will create a new zcash.conf, download zcash parameters. */ void ConnectionLoader::createZcashConf() { - // Create zcash.conf - { + // Fetch params. After params are fetched, create the zcash.conf file and + // try loading the connection again + downloadParams([=] () { auto confLocation = zcashConfWritableLocation(); qDebug() << "Creating file " << confLocation; @@ -94,10 +95,9 @@ void ConnectionLoader::createZcashConf() { out << "rpcuser=zec-qt-wallet\n"; out << "rpcpassword=" % QString::number(std::rand()) << "\n"; file.close(); - } - // Fetch params. After params are fetched, try loading the connection again - downloadParams([=] () { this->loadConnection(); }); + this->loadConnection(); + }); } void ConnectionLoader::downloadParams(std::function cb) { From 595a8d477aed99de706e97638c2dabe774202bce Mon Sep 17 00:00:00 2001 From: adityapk Date: Thu, 8 Nov 2018 13:06:30 -0800 Subject: [PATCH 17/23] zcashd on windows --- src/connection.cpp | 29 +++++++++++++++++++++++------ src/connection.ui | 2 +- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index 231ed93..67bf1c1 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -70,6 +70,23 @@ void ConnectionLoader::loadConnection() { } } +QString randomPassword() { + static const char alphanum[] = + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + + const int passwordLength = 10; + char* s = new char[passwordLength + 1]; + + for (int i = 0; i < passwordLength; ++i) { + s[i] = alphanum[rand() % (sizeof(alphanum) - 1)]; + } + + s[passwordLength] = 0; + return QString::fromStdString(s); +} + /** * This will create a new zcash.conf, download zcash parameters. */ @@ -93,13 +110,14 @@ void ConnectionLoader::createZcashConf() { out << "server=1\n"; out << "rpcuser=zec-qt-wallet\n"; - out << "rpcpassword=" % QString::number(std::rand()) << "\n"; + out << "rpcpassword=" % randomPassword() << "\n"; file.close(); this->loadConnection(); }); } + void ConnectionLoader::downloadParams(std::function cb) { // Add all the files to the download queue downloadQueue = new QQueue(); @@ -216,20 +234,19 @@ bool ConnectionLoader::startEmbeddedZcashd() { qDebug() << "Starting zcashd"; QFileInfo fi(Settings::getInstance()->getExecName()); #ifdef Q_OS_LINUX - auto zcashdProgram = "zcashd"; + auto zcashdProgram = fi.dir().absoluteFilePath("zcashd"); #elif defined(Q_OS_DARWIN) - auto zcashdProgram = "zcashd"; + auto zcashdProgram = fi.dir().absoluteFilePath("zcashd"); #else - auto zcashdProgram = "zcashd.exe"; + auto zcashdProgram = fi.dir().absoluteFilePath("zcashd.exe"); #endif if (!QFile(zcashdProgram).exists()) { - qDebug() << "Can't find zcashd"; + qDebug() << "Can't find zcashd at " << zcashdProgram; return false; } ezcashd = new QProcess(main); - ezcashd->setWorkingDirectory(fi.dir().absolutePath()); QObject::connect(ezcashd, &QProcess::started, [=] () { qDebug() << "zcashd started"; }); diff --git a/src/connection.ui b/src/connection.ui index 704f9d9..9a33ed6 100644 --- a/src/connection.ui +++ b/src/connection.ui @@ -52,7 +52,7 @@ - Connection Status + Starting Up Qt::AlignCenter From acb06ab588ec832dc0d4b4cb0e9d4b837cb93e43 Mon Sep 17 00:00:00 2001 From: adityapk Date: Thu, 8 Nov 2018 13:27:56 -0800 Subject: [PATCH 18/23] Add support for syncing --- src/rpc.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/rpc.cpp b/src/rpc.cpp index db5da25..91d7876 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -519,6 +519,18 @@ void RPC::getInfoThenRefresh(bool force) { Settings::getInstance()->setSyncing(isSyncing); Settings::getInstance()->setBlockNumber(blockNumber); + // Update zcashd tab if it exists + if (ezcashd && isSyncing) { + // 895 / ~426530 (0 % ) + const qint64 genisisTimeMSec = 1477638000000; + qint64 estBlocks = (QDateTime::currentMSecsSinceEpoch() - genisisTimeMSec) / 2.5 / 60 / 1000; + // Round to nearest 10 + estBlocks = ((estBlocks + 5) / 10) * 10; + ui->blockheight->setText(ui->blockheight->text() % " / ~" % QString::number(estBlocks) % + " ( " % QString::number(progress * 100, 'f', 0) % "% )"); + } + + // Update the status bar QString statusText = QString() % (isSyncing ? "Syncing" : "Connected") % " (" % From b1a5d6ec696b5da4370f649f9d984dd95e8a2fb9 Mon Sep 17 00:00:00 2001 From: adityapk Date: Thu, 8 Nov 2018 14:05:59 -0800 Subject: [PATCH 19/23] Make startup window modal, other small fixes --- src/connection.cpp | 29 +++++++++++++++-------------- src/connection.h | 2 +- src/mainwindow.cpp | 14 +++++++------- src/mainwindow.ui | 12 ++++++------ src/rpc.cpp | 27 +++++++++++++-------------- src/rpc.h | 4 +--- 6 files changed, 43 insertions(+), 45 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index 67bf1c1..527d517 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -16,13 +16,6 @@ ConnectionLoader::ConnectionLoader(MainWindow* main, RPC* rpc) { connD = new Ui_ConnectionDialog(); connD->setupUi(d); connD->topIcon->setBasePixmap(QIcon(":/icons/res/icon.ico").pixmap(256, 256)); - - // Center on screen - QRect screenGeometry = QApplication::desktop()->screenGeometry(d); - int x = (screenGeometry.width() - d->width()) / 2; - int y = (screenGeometry.height() - d->height()) / 2; - d->move(x, y); - } ConnectionLoader::~ConnectionLoader() { @@ -31,7 +24,11 @@ ConnectionLoader::~ConnectionLoader() { } void ConnectionLoader::loadConnection() { - d->show(); + QTimer::singleShot(1, [=]() { this->doAutoConnect(); }); + d->exec(); +} + +void ConnectionLoader::doAutoConnect() { // Priority 1: Try to connect to detect zcash.conf and connect to it. auto config = autoDetectZcashConf(); @@ -44,7 +41,7 @@ void ConnectionLoader::loadConnection() { this->showInformation("Starting Embedded zcashd"); if (this->startEmbeddedZcashd()) { // Embedded zcashd started up. Wait a second and then refresh the connection - QTimer::singleShot(1000, [=]() { loadConnection(); } ); + QTimer::singleShot(1000, [=]() { doAutoConnect(); } ); } else { // Errored out, show error and exit QString explanation = QString() % "Couldn't start the embedded zcashd.\n\n" % @@ -113,7 +110,7 @@ void ConnectionLoader::createZcashConf() { out << "rpcpassword=" % randomPassword() << "\n"; file.close(); - this->loadConnection(); + this->doAutoConnect(); }); } @@ -294,11 +291,13 @@ void ConnectionLoader::doManualConnect() { } void ConnectionLoader::doRPCSetConnection(Connection* conn) { - if (ezcashd != nullptr) { + if (ezcashd) { rpc->setEZcashd(ezcashd); } rpc->setConnection(conn); + d->accept(); + delete this; } @@ -367,10 +366,12 @@ void ConnectionLoader::showInformation(QString info, QString detail) { /** * Show error will close the loading dialog and show an error. */ -void ConnectionLoader::showError(QString explanation) { - d->hide(); - main->ui->statusBar->showMessage("Connection Error"); +void ConnectionLoader::showError(QString explanation) { + rpc->setEZcashd(nullptr); + rpc->noConnection(); + QMessageBox::critical(main, "Connection Error", explanation, QMessageBox::Ok); + d->close(); } QString ConnectionLoader::locateZcashConfFile() { diff --git a/src/connection.h b/src/connection.h index 95e157f..f416653 100644 --- a/src/connection.h +++ b/src/connection.h @@ -41,6 +41,7 @@ private: Connection* makeConnection(std::shared_ptr config); + void doAutoConnect(); void doManualConnect(); void createZcashConf(); @@ -53,7 +54,6 @@ private: bool startEmbeddedZcashd(); void refreshZcashdState(Connection* connection, std::function refused); - int getProgressFromStatus(QString status); void showError(QString explanation); void showInformation(QString info, QString detail = ""); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index fd489dd..505f209 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -373,13 +373,6 @@ void MainWindow::setupSettingsModal() { QIntValidator validator(0, 65535); settings.port->setValidator(&validator); - // Load current values into the dialog - auto conf = Settings::getInstance()->getSettings(); - settings.hostname->setText(conf.host); - settings.port->setText(conf.port); - settings.rpcuser->setText(conf.rpcuser); - settings.rpcpassword->setText(conf.rpcpassword); - // If values are coming from zcash.conf, then disable all the fields auto zcashConfLocation = Settings::getInstance()->getZcashdConfLocation(); if (!zcashConfLocation.isEmpty()) { @@ -390,6 +383,13 @@ void MainWindow::setupSettingsModal() { settings.rpcpassword->setEnabled(false); } else { + // Load current values into the dialog + auto conf = Settings::getInstance()->getSettings(); + settings.hostname->setText(conf.host); + settings.port->setText(conf.port); + settings.rpcuser->setText(conf.rpcuser); + settings.rpcpassword->setText(conf.rpcpassword); + settings.confMsg->setText("No local zcash.conf found. Please configure connection manually."); settings.hostname->setEnabled(true); settings.port->setEnabled(true); diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 3fc26f4..0a4aacd 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -316,8 +316,8 @@ 0 0 - 920 - 334 + 922 + 376 @@ -767,7 +767,7 @@ - TextLabel + Loading... @@ -781,7 +781,7 @@ - TextLabel + Loading... @@ -802,7 +802,7 @@ - TextLabel + Loading... @@ -864,7 +864,7 @@ 0 0 968 - 22 + 21 diff --git a/src/rpc.cpp b/src/rpc.cpp index 91d7876..20b521e 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -9,8 +9,8 @@ using json = nlohmann::json; RPC::RPC(MainWindow* main) { auto cl = new ConnectionLoader(main, this); - // Show a default no connection message until we can connect. - cl->loadConnection(); + // Execute the load connection async, so we can set up the rest of RPC properly. + QTimer::singleShot(1, [=]() {cl->loadConnection(); }); this->main = main; this->ui = main->ui; @@ -66,6 +66,9 @@ RPC::~RPC() { void RPC::setEZcashd(QProcess* p) { ezcashd = p; + + if (ezcashd == nullptr) + ui->tabWidget->removeTab(4); } void RPC::setConnection(Connection* c) { @@ -326,8 +329,10 @@ void RPC::fillTxJsonParams(json& params, Tx tx) { } -void RPC::noConnection() { - ui->statusBar->showMessage("No Connection to zcashd"); +void RPC::noConnection() { + QIcon i = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical); + main->statusIcon->setPixmap(i.pixmap(16, 16)); + main->statusLabel->setText("No Connection"); } // Refresh received z txs by calling z_listreceivedbyaddress/gettransaction @@ -439,7 +444,6 @@ void RPC::refreshReceivedZTrans(QList zaddrs) { ); } - /// This will refresh all the balance data from zcashd void RPC::refresh(bool force) { if (conn == nullptr) @@ -482,7 +486,7 @@ void RPC::getInfoThenRefresh(bool force) { } // Get network sol/s - if (ezcashd != nullptr) { + if (ezcashd) { int conns = reply["connections"].get(); json payload = { @@ -498,11 +502,7 @@ void RPC::getInfoThenRefresh(bool force) { ui->numconnections->setText(QString::number(conns)); ui->solrate->setText(QString::number(solrate) % " Sol/s"); }); - } else { - qDebug() << "removing tab!"; - ui->tabWidget->removeTab(4); - } - + } // Call to see if the blockchain is syncing. json payload = { @@ -526,7 +526,7 @@ void RPC::getInfoThenRefresh(bool force) { qint64 estBlocks = (QDateTime::currentMSecsSinceEpoch() - genisisTimeMSec) / 2.5 / 60 / 1000; // Round to nearest 10 estBlocks = ((estBlocks + 5) / 10) * 10; - ui->blockheight->setText(ui->blockheight->text() % " / ~" % QString::number(estBlocks) % + ui->blockheight->setText(ui->blockheight->text() % /*" / ~" % QString::number(estBlocks) % */ " ( " % QString::number(progress * 100, 'f', 0) % "% )"); } @@ -871,11 +871,10 @@ void RPC::shutdownZcashd() { conn->doRPCWithDefaultErrorHandling(payload, [=](auto) {}); conn->shutdown(); - QMessageBox d(main); d.setIcon(QMessageBox::Icon::Information); d.setWindowTitle("Waiting for zcashd to exit"); - d.setText("Please wait for zcashd to exit. Don't click OK!"); + d.setText("Please wait for zcashd to exit."); d.setStandardButtons(QMessageBox::NoButton); QTimer waiter(main); diff --git a/src/rpc.h b/src/rpc.h index 6d2d8e9..958a733 100644 --- a/src/rpc.h +++ b/src/rpc.h @@ -59,16 +59,14 @@ public: void importTPrivKey(QString addr, bool rescan, const std::function& cb); void shutdownZcashd(); + void noConnection(); void getAllPrivKeys(const std::function>)>); Turnstile* getTurnstile() { return turnstile; } Connection* getConnection() { return conn; } - private: - void noConnection(); - void refreshBalances(); void refreshTransactions(); From 71f4433a394ed1f08f995a643f0aae205e8587c5 Mon Sep 17 00:00:00 2001 From: adityapk Date: Thu, 8 Nov 2018 14:43:10 -0800 Subject: [PATCH 20/23] cleanup --- src/connection.cpp | 4 ++-- src/rpc.cpp | 7 +++++-- src/senttxstore.cpp | 4 ++-- src/settings.cpp | 5 +---- src/turnstile.cpp | 8 ++------ src/turnstile.h | 1 - 6 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index 527d517..14e1841 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -265,7 +265,7 @@ bool ConnectionLoader::startEmbeddedZcashd() { void ConnectionLoader::doManualConnect() { auto config = loadFromSettings(); - if (config.get() == nullptr) { + if (!config) { // Nothing configured, show an error QString explanation = QString() % "A manual connection was requested, but the settings are not configured.\n\n" @@ -569,4 +569,4 @@ void Connection::showTxError(const QString& error) { */ void Connection::shutdown() { shutdownInProgress = true; -} \ No newline at end of file +} diff --git a/src/rpc.cpp b/src/rpc.cpp index 20b521e..e8c2077 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -837,7 +837,7 @@ void RPC::refreshZECPrice() { } for (const json& item : parsed.get()) { - if (item["symbol"].get().compare("ZEC") == 0) { + if (item["symbol"].get() == "ZEC") { QString price = QString::fromStdString(item["price_usd"].get()); qDebug() << "ZEC Price=" << price; Settings::getInstance()->setZECPrice(price.toDouble()); @@ -881,8 +881,11 @@ void RPC::shutdownZcashd() { // 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, [&] () { - if (ezcashd->atEnd() && ezcashd->processId() == 0) { + waitCount++; + if ((ezcashd->atEnd() && ezcashd->processId() == 0) || + waitCount > 30) { qDebug() << "Ended"; waiter.stop(); QTimer::singleShot(1000, [&]() { d.accept(); }); diff --git a/src/senttxstore.cpp b/src/senttxstore.cpp index f5d587d..bb77a8b 100644 --- a/src/senttxstore.cpp +++ b/src/senttxstore.cpp @@ -31,7 +31,7 @@ QList SentTxStore::readSentTxFile() { QJsonDocument jsonDoc; data.open(QFile::ReadOnly); - jsonDoc = QJsonDocument().fromJson(data.readAll()); + jsonDoc = QJsonDocument::fromJson(data.readAll()); data.close(); QList items; @@ -87,7 +87,7 @@ void SentTxStore::addToSentTx(Tx tx, QString txid) { QJsonObject txItem; txItem["type"] = "sent"; txItem["from"] = tx.fromAddr; - txItem["datetime"] = QDateTime().currentMSecsSinceEpoch() / (qint64)1000; + txItem["datetime"] = QDateTime::currentMSecsSinceEpoch() / (qint64)1000; txItem["address"] = QString(); // The sent address is blank, to be consistent with t-Addr sent behaviour txItem["txid"] = txid; txItem["amount"] = -totalAmount; diff --git a/src/settings.cpp b/src/settings.cpp index fa7fa9a..38fee88 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -5,9 +5,6 @@ Settings* Settings::instance = nullptr; -Settings::~Settings() { -} - bool Settings::getSaveZtxs() { // Load from the QT Settings. return QSettings().value("options/savesenttx", true).toBool(); @@ -122,4 +119,4 @@ QString Settings::getZECUSDDisplayFormat(double bal) { return getZECDisplayFormat(bal) % " (" % getUSDFormat(bal) % ")"; else return getZECDisplayFormat(bal); -} \ No newline at end of file +} diff --git a/src/turnstile.cpp b/src/turnstile.cpp index fb2211f..64ec6e0 100644 --- a/src/turnstile.cpp +++ b/src/turnstile.cpp @@ -14,8 +14,6 @@ Turnstile::Turnstile(RPC* _rpc, MainWindow* mainwindow) { this->mainwindow = mainwindow; } -Turnstile::~Turnstile() { -} void printPlan(QList plan) { for (auto item : plan) { @@ -118,7 +116,7 @@ void Turnstile::planMigration(QString zaddr, QString destAddr, int numsplits, in // The first migration is shifted to the current block, so the user sees something // happening immediately - if (migItems.size() == 0) { + if (migItems.empty()) { // Show error and abort QMessageBox::warning(mainwindow, "Locked funds", @@ -220,9 +218,7 @@ Turnstile::getNextStep(QList& plan) { bool Turnstile::isMigrationPresent() { auto plan = readMigrationPlan(); - if (plan.isEmpty()) return false; - - return true; + return !plan.isEmpty(); } ProgressReport Turnstile::getPlanProgress() { diff --git a/src/turnstile.h b/src/turnstile.h index a73af50..aba1a3e 100644 --- a/src/turnstile.h +++ b/src/turnstile.h @@ -39,7 +39,6 @@ class Turnstile { public: Turnstile(RPC* _rpc, MainWindow* mainwindow); - ~Turnstile(); void planMigration(QString zaddr, QString destAddr, int splits, int numBlocks); QList splitAmount(double amount, int parts); From 95e2c0280c6e5b914f29b37a4542d5885f337615 Mon Sep 17 00:00:00 2001 From: adityapk Date: Thu, 8 Nov 2018 15:01:27 -0800 Subject: [PATCH 21/23] change exit splash screen --- src/rpc.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/rpc.cpp b/src/rpc.cpp index e8c2077..11ca9ae 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -871,12 +871,13 @@ void RPC::shutdownZcashd() { conn->doRPCWithDefaultErrorHandling(payload, [=](auto) {}); conn->shutdown(); - QMessageBox d(main); - d.setIcon(QMessageBox::Icon::Information); - d.setWindowTitle("Waiting for zcashd to exit"); - d.setText("Please wait for zcashd to exit."); - d.setStandardButtons(QMessageBox::NoButton); - + QDialog d(main); + Ui_ConnectionDialog connD; + connD.setupUi(&d); + connD.topIcon->setBasePixmap(QIcon(":/icons/res/icon.ico").pixmap(256, 256)); + connD.status->setText("Please wait for zec-qt-wallet to exit"); + connD.statusDetail->setText("Waiting for zcashd to exit"); + QTimer waiter(main); // We capture by reference all the local variables because of the d.exec() From 0429b592aab41c7cf88cfc7d487837c33b4bbb6f Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Fri, 9 Nov 2018 14:46:21 -0800 Subject: [PATCH 22/23] build with embedded zcashd --- src/connection.cpp | 2 +- src/scripts/mkrelease.sh | 73 ++++++++++++++++++++++++++-------------- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index 231ed93..8c1e268 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -333,7 +333,7 @@ void ConnectionLoader::refreshZcashdState(Connection* connection, std::function< !res.is_discarded()) { // The server is loading, so just poll until it succeeds QString status = QString::fromStdString(res["error"]["message"]); - showInformation("Your zcashd is starting up. Please wait.", status); + this->showInformation("Your zcashd is starting up. Please wait.", status); // Refresh after one second QTimer::singleShot(1000, [=]() { this->refreshZcashdState(connection, refused); }); diff --git a/src/scripts/mkrelease.sh b/src/scripts/mkrelease.sh index 5b4d291..aba3c0e 100755 --- a/src/scripts/mkrelease.sh +++ b/src/scripts/mkrelease.sh @@ -9,7 +9,17 @@ if [ -z $MXE_PATH ]; then echo "MXE_PATH is not set. Set it to ~/github/mxe/usr/ if [ -z $APP_VERSION ]; then echo "APP_VERSION is not set"; exit 1; fi if [ -z $PREV_VERSION ]; then echo "PREV_VERSION is not set"; exit 1; fi -echo -n "Version files." +if [ ! -f ../zcash/artifacts/zcashd ]; then + echo "Couldn't find zcashd in ../zcash/artifacts/. Please build zcashd." + exit 1; +fi + +if [ ! -f ../zcash/artifacts/zcashd.exe ]; then + echo "Couldn't find zcashd.exe in ../zcash/artifacts/. Please build zcashd.exe" + exit 1; +fi + +echo -n "Version files....." # Replace the version number in the .pro file so it gets picked up everywhere sed -i "s/${PREV_VERSION}/${APP_VERSION}/g" zec-qt-wallet.pro > /dev/null @@ -17,28 +27,28 @@ sed -i "s/${PREV_VERSION}/${APP_VERSION}/g" zec-qt-wallet.pro > /dev/null sed -i "s/${PREV_VERSION}/${APP_VERSION}/g" README.md > /dev/null echo "[OK]" -echo -n "Cleaning......" -rm -f bin/linux-zec-qt-wallet* -rm -rf release/ +echo -n "Cleaning.........." +rm -rf bin/* make distclean > /dev/null echo "[OK]" -echo "Linux" +echo "" +echo "[Linux]" -echo -n "Configuring..." +echo -n "Configuring......." $QT_STATIC/bin/qmake zec-qt-wallet.pro -spec linux-clang CONFIG+=release > /dev/null #Mingw seems to have trouble with precompiled headers, so strip that option from the .pro file echo "[OK]" -echo -n "Building......" +echo -n "Building.........." rm -rf bin/zec-qt-wallet* > /dev/null make -j$(nproc) > /dev/null echo "[OK]" # Test for Qt -echo -n "Static link..." +echo -n "Static link......." if [[ $(ldd zec-qt-wallet | grep -i "Qt") ]]; then echo "FOUND QT; ABORT"; exit 1 @@ -46,32 +56,37 @@ fi echo "[OK]" -echo -n "Packaging....." +echo -n "Packaging........." mkdir bin/zec-qt-wallet-v$APP_VERSION > /dev/null cp zec-qt-wallet bin/zec-qt-wallet-v$APP_VERSION > /dev/null +cp ../zcash/artifacts/zcashd bin/zec-qt-wallet-v$APP_VERSION > /dev/null cp README.md bin/zec-qt-wallet-v$APP_VERSION > /dev/null cp LICENSE bin/zec-qt-wallet-v$APP_VERSION > /dev/null cd bin && tar cvf linux-zec-qt-wallet-v$APP_VERSION.tar.gz zec-qt-wallet-v$APP_VERSION/ > /dev/null cd .. mkdir artifacts >/dev/null 2>&1 cp bin/linux-zec-qt-wallet-v$APP_VERSION.tar.gz ./artifacts +echo "[OK]" + if [ -f artifacts/linux-zec-qt-wallet-v$APP_VERSION.tar.gz ] ; then - echo "[OK]" - - echo "Done. Build is artifacts/linux-zec-qt-wallet-v$APP_VERSION.tar.gz" - echo "Package contents:" - tar tf "artifacts/linux-zec-qt-wallet-v$APP_VERSION.tar.gz" + echo -n "Package contents.." + # Test if the package is built OK + if tar tf "artifacts/linux-zec-qt-wallet-v$APP_VERSION.tar.gz" | wc -l | grep -q "5"; then + echo "[OK]" + else + exit 1 + fi else echo "[ERROR]" exit 1 fi -echo "Windows" - +echo "" +echo "[Windows]" export PATH=$MXE_PATH:$PATH -echo -n "Configuring..." +echo -n "Configuring......." make clean > /dev/null rm -f zec-qt-wallet-mingw.pro rm -rf release/ @@ -80,30 +95,38 @@ cat zec-qt-wallet.pro | sed "s/precompile_header/release/g" | sed "s/PRECOMPILED echo "[OK]" -echo -n "Building......" +echo -n "Building.........." x86_64-w64-mingw32.static-qmake-qt5 zec-qt-wallet-mingw.pro CONFIG+=release > /dev/null make -j32 > /dev/null echo "[OK]" -echo -n "Packaging....." +echo -n "Packaging........." mkdir release/zec-qt-wallet-v$APP_VERSION cp release/zec-qt-wallet.exe release/zec-qt-wallet-v$APP_VERSION +cp ../zcash/artifacts/zcashd.exe release/zec-qt-wallet-v$APP_VERSION > /dev/null cp README.md release/zec-qt-wallet-v$APP_VERSION cp LICENSE release/zec-qt-wallet-v$APP_VERSION cd release && zip -r Windows-zec-qt-wallet-v$APP_VERSION.zip zec-qt-wallet-v$APP_VERSION/ > /dev/null cd .. mkdir artifacts >/dev/null 2>&1 cp release/Windows-zec-qt-wallet-v$APP_VERSION.zip ./artifacts - +echo "[OK]" if [ -f artifacts/Windows-zec-qt-wallet-v$APP_VERSION.zip ] ; then - echo "[OK]" - - echo "Done. Build is artifacts/Windows-zec-qt-wallet-v$APP_VERSION.zip" - echo "Package contents:" - unzip -l "artifacts/Windows-zec-qt-wallet-v$APP_VERSION.zip" + echo -n "Package contents.." + if unzip -l "artifacts/Windows-zec-qt-wallet-v$APP_VERSION.zip" | wc -l | grep -q "10"; then + echo "[OK]" + else + echo "[ERROR]" + exit 1 + fi + else echo "[ERROR]" exit 1 fi + +echo "" +echo "Build is artifacts/Windows-zec-qt-wallet-v$APP_VERSION.zip" +echo "Build is artifacts/linux-zec-qt-wallet-v$APP_VERSION.tar.gz" \ No newline at end of file From 7e6f6f6db403d684fb36b1a04230274cba66cfaa Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Fri, 9 Nov 2018 15:00:49 -0800 Subject: [PATCH 23/23] remove tab when connecting to external zcashd --- src/connection.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index 157118b..f1f1f26 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -291,11 +291,9 @@ void ConnectionLoader::doManualConnect() { } void ConnectionLoader::doRPCSetConnection(Connection* conn) { - if (ezcashd) { - rpc->setEZcashd(ezcashd); - } - + rpc->setEZcashd(ezcashd); rpc->setConnection(conn); + d->accept(); delete this;