#58 - Verify params on startup

This commit is contained in:
Aditya Kulkarni
2018-11-20 14:41:45 -08:00
parent d8d32233ac
commit 1756c0b239
4 changed files with 71 additions and 28 deletions

View File

@@ -30,8 +30,15 @@ void ConnectionLoader::loadConnection() {
} }
void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) { void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
// Priority 1: Try to connect to detect zcash.conf and connect to it. // Priority 1: Ensure all params are present.
if (!verifyParams()) {
downloadParams([=]() { this->doAutoConnect(); });
return;
}
// Priority 2: Try to connect to detect zcash.conf and connect to it.
auto config = autoDetectZcashConf(); auto config = autoDetectZcashConf();
main->logger->write("Attempting autoconnect");
if (config.get() != nullptr) { if (config.get() != nullptr) {
auto connection = makeConnection(config); auto connection = makeConnection(config);
@@ -43,6 +50,7 @@ void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
this->showInformation("Starting embedded zcashd"); this->showInformation("Starting embedded zcashd");
if (this->startEmbeddedZcashd()) { if (this->startEmbeddedZcashd()) {
// Embedded zcashd started up. Wait a second and then refresh the connection // Embedded zcashd started up. Wait a second and then refresh the connection
main->logger->write("Embedded zcashd started up, trying autoconnect in 1 sec");
QTimer::singleShot(1000, [=]() { doAutoConnect(); } ); QTimer::singleShot(1000, [=]() { doAutoConnect(); } );
} else { } else {
// Something is wrong. This is happenening intermittently on Mac platforms. // Something is wrong. This is happenening intermittently on Mac platforms.
@@ -51,10 +59,12 @@ void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
// - QProcess ended, but the embedded zcashd is still in the background. // - QProcess ended, but the embedded zcashd is still in the background.
// We're going to attempt to connect to the one in the background one last time // We're going to attempt to connect to the one in the background one last time
// and see if that works, else throw an error // and see if that works, else throw an error
main->logger->write("Something is wrong, trying no-retry autoconnect in 2 sec");
QTimer::singleShot(2000, [=]() { doAutoConnect(/* don't attempt to start ezcashd */ false); }); QTimer::singleShot(2000, [=]() { doAutoConnect(/* don't attempt to start ezcashd */ false); });
} }
} else { } else {
// We tried to start ezcashd previously, and it didn't work. So, show the error. // We tried to start ezcashd previously, and it didn't work. So, show the error.
main->logger->write("Couldn't start embedded zcashd for unknown reason");
QString explanation = QString() % "Couldn't start the embedded zcashd.\n\n" % QString explanation = QString() % "Couldn't start the embedded zcashd.\n\n" %
"Please try restarting.\n\nIfIf you previously started zcashd with custom arguments, you might need to reset zcash.conf.\n\n" % "Please try restarting.\n\nIfIf you previously started zcashd with custom arguments, you might need to reset zcash.conf.\n\n" %
"If all else fails, please run zcashd manually." % "If all else fails, please run zcashd manually." %
@@ -64,6 +74,7 @@ void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
} else { } else {
// zcash.conf exists, there's no connection, and the user asked us not to start zcashd. Error! // zcash.conf exists, there's no connection, and the user asked us not to start zcashd. Error!
main->logger->write("Not using embedded and couldn't connect to zcashd");
QString explanation = QString() % "Couldn't connect to zcashd configured in zcash.conf.\n\n" % QString explanation = QString() % "Couldn't connect to zcashd configured in zcash.conf.\n\n" %
"Not starting embedded zcashd because --no-embedded was passed"; "Not starting embedded zcashd because --no-embedded was passed";
this->showError(explanation); this->showError(explanation);
@@ -101,35 +112,35 @@ QString randomPassword() {
* This will create a new zcash.conf, download Zcash parameters. * This will create a new zcash.conf, download Zcash parameters.
*/ */
void ConnectionLoader::createZcashConf() { void ConnectionLoader::createZcashConf() {
// Fetch params. After params are fetched, create the zcash.conf file and main->logger->write("createZcashConf");
// try loading the connection again
downloadParams([=] () {
auto confLocation = zcashConfWritableLocation();
qDebug() << "Creating file " << confLocation;
QFileInfo fi(confLocation); auto confLocation = zcashConfWritableLocation();
QDir().mkdir(fi.dir().absolutePath()); main->logger->write("Creating file " + confLocation);
QFile file(confLocation); QFileInfo fi(confLocation);
if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) { QDir().mkdir(fi.dir().absolutePath());
qDebug() << "Could not create zcash.conf, returning";
return; QFile file(confLocation);
} if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
main->logger->write("Could not create zcash.conf, returning");
QTextStream out(&file); return;
}
out << "server=1\n"; QTextStream out(&file);
out << "addnode=mainnet.z.cash\n";
out << "rpcuser=zec-qt-wallet\n"; out << "server=1\n";
out << "rpcpassword=" % randomPassword() << "\n"; out << "addnode=mainnet.z.cash\n";
file.close(); out << "rpcuser=zec-qt-wallet\n";
out << "rpcpassword=" % randomPassword() << "\n";
file.close();
this->doAutoConnect(); // Now that zcash.conf exists, try to autoconnect again
}); this->doAutoConnect();
} }
void ConnectionLoader::downloadParams(std::function<void(void)> cb) { void ConnectionLoader::downloadParams(std::function<void(void)> cb) {
main->logger->write("Adding params to download queue");
// Add all the files to the download queue // Add all the files to the download queue
downloadQueue = new QQueue<QUrl>(); downloadQueue = new QQueue<QUrl>();
client = new QNetworkAccessManager(main); client = new QNetworkAccessManager(main);
@@ -155,6 +166,7 @@ void ConnectionLoader::doNextDownload(std::function<void(void)> cb) {
delete downloadQueue; delete downloadQueue;
client->deleteLater(); client->deleteLater();
main->logger->write("All Downloads done");
this->showInformation("All Downloads Finished Successfully!"); this->showInformation("All Downloads Finished Successfully!");
cb(); cb();
return; return;
@@ -167,7 +179,7 @@ void ConnectionLoader::doNextDownload(std::function<void(void)> cb) {
QString paramsDir = zcashParamsDir(); QString paramsDir = zcashParamsDir();
if (QFile(QDir(paramsDir).filePath(filename)).exists()) { if (QFile(QDir(paramsDir).filePath(filename)).exists()) {
qDebug() << filename << " already exists, skipping "; main->logger->write(filename + " already exists, skipping");
doNextDownload(cb); doNextDownload(cb);
return; return;
@@ -177,8 +189,10 @@ void ConnectionLoader::doNextDownload(std::function<void(void)> cb) {
currentOutput = new QFile(QDir(paramsDir).filePath(filename + ".part")); currentOutput = new QFile(QDir(paramsDir).filePath(filename + ".part"));
if (!currentOutput->open(QIODevice::WriteOnly)) { if (!currentOutput->open(QIODevice::WriteOnly)) {
main->logger->write("Couldn't open " + currentOutput->fileName() + " for writing");
this->showError("Couldn't download params. Please check the help site for more info."); this->showError("Couldn't download params. Please check the help site for more info.");
} }
main->logger->write("Downloading to " + filename);
qDebug() << "Downloading " << url << " to " << filename; qDebug() << "Downloading " << url << " to " << filename;
QNetworkRequest request(url); QNetworkRequest request(url);
@@ -209,6 +223,7 @@ void ConnectionLoader::doNextDownload(std::function<void(void)> cb) {
// Download Finished // Download Finished
QObject::connect(currentDownload, &QNetworkReply::finished, [=] () { QObject::connect(currentDownload, &QNetworkReply::finished, [=] () {
// Rename file // Rename file
main->logger->write("Finished downloading " + filename);
currentOutput->rename(QDir(paramsDir).filePath(filename)); currentOutput->rename(QDir(paramsDir).filePath(filename));
currentOutput->close(); currentOutput->close();
@@ -216,7 +231,8 @@ void ConnectionLoader::doNextDownload(std::function<void(void)> cb) {
currentOutput->deleteLater(); currentOutput->deleteLater();
if (currentDownload->error()) { if (currentDownload->error()) {
this->showError("Downloading " + filename + " failed/ Please check the help site for more info"); main->logger->write("Downloading " + filename + " failed");
this->showError("Downloading " + filename + " failed. Please check the help site for more info");
} else { } else {
doNextDownload(cb); doNextDownload(cb);
} }
@@ -231,6 +247,8 @@ void ConnectionLoader::doNextDownload(std::function<void(void)> cb) {
bool ConnectionLoader::startEmbeddedZcashd() { bool ConnectionLoader::startEmbeddedZcashd() {
if (!Settings::getInstance()->useEmbedded()) if (!Settings::getInstance()->useEmbedded())
return false; return false;
main->logger->write("Trying to start embedded zcashd");
// Static because it needs to survive even after this method returns. // Static because it needs to survive even after this method returns.
static QString processStdErrOutput; static QString processStdErrOutput;
@@ -263,6 +281,7 @@ bool ConnectionLoader::startEmbeddedZcashd() {
if (!QFile(zcashdProgram).exists()) { if (!QFile(zcashdProgram).exists()) {
qDebug() << "Can't find zcashd at " << zcashdProgram; qDebug() << "Can't find zcashd at " << zcashdProgram;
main->logger->write("Can't find zcashd at " + zcashdProgram);
return false; return false;
} }
@@ -282,7 +301,7 @@ bool ConnectionLoader::startEmbeddedZcashd() {
QObject::connect(ezcashd, &QProcess::readyReadStandardError, [=]() { QObject::connect(ezcashd, &QProcess::readyReadStandardError, [=]() {
auto output = ezcashd->readAllStandardError(); auto output = ezcashd->readAllStandardError();
qDebug() << "zcashd stderr:" << output; main->logger->write("zcashd stderr:" + output);
processStdErrOutput.append(output); processStdErrOutput.append(output);
}); });
@@ -375,6 +394,7 @@ void ConnectionLoader::refreshZcashdState(Connection* connection, std::function<
if (err == QNetworkReply::NetworkError::ConnectionRefusedError) { if (err == QNetworkReply::NetworkError::ConnectionRefusedError) {
refused(); refused();
} else if (err == QNetworkReply::NetworkError::AuthenticationRequiredError) { } else if (err == QNetworkReply::NetworkError::AuthenticationRequiredError) {
main->logger->write("Authentication failed");
QString explanation = QString() QString explanation = QString()
% "Authentication failed. The username / password you specified was " % "Authentication failed. The username / password you specified was "
% "not accepted by zcashd. Try changing it in the Edit->Settings menu"; % "not accepted by zcashd. Try changing it in the Edit->Settings menu";
@@ -392,7 +412,7 @@ void ConnectionLoader::refreshZcashdState(Connection* connection, std::function<
dots = 0; dots = 0;
} }
this->showInformation("Your zcashd is starting up. Please wait.", status); this->showInformation("Your zcashd is starting up. Please wait.", status);
main->logger->write("Waiting to zcashd to come online.");
// Refresh after one second // Refresh after one second
QTimer::singleShot(1000, [=]() { this->refreshZcashdState(connection, refused); }); QTimer::singleShot(1000, [=]() { this->refreshZcashdState(connection, refused); });
} }
@@ -424,6 +444,8 @@ QString ConnectionLoader::locateZcashConfFile() {
#else #else
auto confLocation = QStandardPaths::locate(QStandardPaths::AppDataLocation, "../../Zcash/zcash.conf"); auto confLocation = QStandardPaths::locate(QStandardPaths::AppDataLocation, "../../Zcash/zcash.conf");
#endif #endif
main->logger->write("Found zcashconf at " + QDir::cleanPath(confLocation));
return QDir::cleanPath(confLocation); return QDir::cleanPath(confLocation);
} }
@@ -436,7 +458,8 @@ QString ConnectionLoader::zcashConfWritableLocation() {
auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("../../Zcash/zcash.conf"); auto confLocation = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("../../Zcash/zcash.conf");
#endif #endif
return confLocation; main->logger->write("Found zcashconf at " + QDir::cleanPath(confLocation));
return QDir::cleanPath(confLocation);
} }
QString ConnectionLoader::zcashParamsDir() { QString ConnectionLoader::zcashParamsDir() {
@@ -449,12 +472,26 @@ QString ConnectionLoader::zcashParamsDir() {
#endif #endif
if (!paramsLocation.exists()) { if (!paramsLocation.exists()) {
main->logger->write("Creating params location at " + paramsLocation.absolutePath());
QDir().mkpath(paramsLocation.absolutePath()); QDir().mkpath(paramsLocation.absolutePath());
} }
main->logger->write("Found zcash params directory at " + paramsLocation.absolutePath());
return paramsLocation.absolutePath(); return paramsLocation.absolutePath();
} }
bool ConnectionLoader::verifyParams() {
QDir paramsDir(zcashParamsDir());
if (!QFile(paramsDir.filePath("sapling-output.params")).exists()) return false;
if (!QFile(paramsDir.filePath("sapling-spend.params")).exists()) return false;
if (!QFile(paramsDir.filePath("sprout-proving.key")).exists()) return false;
if (!QFile(paramsDir.filePath("sprout-verifying.key")).exists()) return false;
if (!QFile(paramsDir.filePath("sprout-groth16.params")).exists()) return false;
return true;
}
/** /**
* Try to automatically detect a zcash.conf file in the correct location and load parameters * Try to automatically detect a zcash.conf file in the correct location and load parameters
*/ */
@@ -506,9 +543,10 @@ std::shared_ptr<ConnectionConfig> ConnectionLoader::autoDetectZcashConf() {
// If rpcport is not in the file, and it was not set by the testnet=1 flag, then go to default // If rpcport is not in the file, and it was not set by the testnet=1 flag, then go to default
if (zcashconf->port.isEmpty()) zcashconf->port = "8232"; if (zcashconf->port.isEmpty()) zcashconf->port = "8232";
file.close(); file.close();
// In addition to the zcash.conf file, also double check the params.
return std::shared_ptr<ConnectionConfig>(zcashconf); return std::shared_ptr<ConnectionConfig>(zcashconf);
} }

View File

@@ -50,6 +50,7 @@ private:
QString zcashConfWritableLocation(); QString zcashConfWritableLocation();
QString zcashParamsDir(); QString zcashParamsDir();
bool verifyParams();
void downloadParams(std::function<void(void)> cb); void downloadParams(std::function<void(void)> cb);
void doNextDownload(std::function<void(void)> cb); void doNextDownload(std::function<void(void)> cb);
bool startEmbeddedZcashd(); bool startEmbeddedZcashd();

View File

@@ -23,6 +23,7 @@ MainWindow::MainWindow(QWidget *parent) :
ui(new Ui::MainWindow) ui(new Ui::MainWindow)
{ {
ui->setupUi(this); ui->setupUi(this);
logger = new Logger(this, QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("zec-qt-wallet.log"));
// Status Bar // Status Bar
setupStatusBar(); setupStatusBar();
@@ -1040,4 +1041,5 @@ MainWindow::~MainWindow()
delete labelCompleter; delete labelCompleter;
delete loadingMovie; delete loadingMovie;
delete logger;
} }

View File

@@ -2,6 +2,7 @@
#define MAINWINDOW_H #define MAINWINDOW_H
#include "precompiled.h" #include "precompiled.h"
#include "logger.h"
// Forward declare to break circular dependency. // Forward declare to break circular dependency.
class RPC; class RPC;
@@ -45,6 +46,7 @@ public:
QLabel* loadingLabel; QLabel* loadingLabel;
QWidget* zcashdtab; QWidget* zcashdtab;
Logger* logger;
private: private:
void closeEvent(QCloseEvent* event); void closeEvent(QCloseEvent* event);