From 595a8d477aed99de706e97638c2dabe774202bce Mon Sep 17 00:00:00 2001 From: adityapk Date: Thu, 8 Nov 2018 13:06:30 -0800 Subject: [PATCH 1/5] 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 2/5] 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 3/5] 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 4/5] 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 5/5] 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()