WIP
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
#include "ui_createzcashconfdialog.h"
|
||||
#include "controller.h"
|
||||
|
||||
#include "../lib/zecwalletlitelib.h"
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
using json = nlohmann::json;
|
||||
@@ -32,15 +34,24 @@ void ConnectionLoader::loadConnection() {
|
||||
}
|
||||
|
||||
void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
|
||||
// Priority 1: Ensure all params are present.
|
||||
if (!verifyParams()) {
|
||||
downloadParams([=]() { this->doAutoConnect(); });
|
||||
return;
|
||||
}
|
||||
auto config = std::shared_ptr<ConnectionConfig>(new ConnectionConfig());
|
||||
config->dangerous = true;
|
||||
config->server = QString("https://127.0.0.1:9067");
|
||||
|
||||
// Initialize the library
|
||||
main->logger->write(QObject::tr("Attempting to initialize"));
|
||||
litelib_initialze(config->dangerous, config->server.toStdString());
|
||||
auto connection = makeConnection(config);
|
||||
|
||||
// After the lib is initialized, try to do get info
|
||||
connection->doRPC("info", [=](auto reply) {
|
||||
// If success, set the connection
|
||||
d->hide();
|
||||
main->logger->write("Connection is online.");
|
||||
this->doRPCSetConnection(connection);
|
||||
}, [=](auto err, auto errJson) {});
|
||||
|
||||
|
||||
// Priority 2: Try to connect to detect zcash.conf and connect to it.
|
||||
auto config = autoDetectZcashConf();
|
||||
main->logger->write(QObject::tr("Attempting autoconnect"));
|
||||
|
||||
if (config.get() != nullptr) {
|
||||
auto connection = makeConnection(config);
|
||||
@@ -106,318 +117,6 @@ void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
|
||||
}
|
||||
}
|
||||
|
||||
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[randombytes_uniform(sizeof(alphanum))];
|
||||
}
|
||||
|
||||
s[passwordLength] = 0;
|
||||
return QString::fromStdString(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will create a new zcash.conf, download Zcash parameters.
|
||||
*/
|
||||
void ConnectionLoader::createZcashConf() {
|
||||
main->logger->write("createZcashConf");
|
||||
|
||||
auto confLocation = zcashConfWritableLocation();
|
||||
QFileInfo fi(confLocation);
|
||||
|
||||
QDialog d(main);
|
||||
Ui_createZcashConf ui;
|
||||
ui.setupUi(&d);
|
||||
|
||||
QPixmap logo(":/img/res/zcashdlogo.gif");
|
||||
ui.lblTopIcon->setBasePixmap(logo.scaled(256, 256, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
ui.btnPickDir->setEnabled(false);
|
||||
|
||||
ui.grpAdvanced->setVisible(false);
|
||||
QObject::connect(ui.btnAdvancedConfig, &QPushButton::toggled, [=](bool isVisible) {
|
||||
ui.grpAdvanced->setVisible(isVisible);
|
||||
ui.btnAdvancedConfig->setText(isVisible ? QObject::tr("Hide Advanced Config") : QObject::tr("Show Advanced Config"));
|
||||
});
|
||||
|
||||
QObject::connect(ui.chkCustomDatadir, &QCheckBox::stateChanged, [=](int chked) {
|
||||
if (chked == Qt::Checked) {
|
||||
ui.btnPickDir->setEnabled(true);
|
||||
}
|
||||
else {
|
||||
ui.btnPickDir->setEnabled(false);
|
||||
}
|
||||
});
|
||||
|
||||
QObject::connect(ui.btnPickDir, &QPushButton::clicked, [=]() {
|
||||
auto datadir = QFileDialog::getExistingDirectory(main, QObject::tr("Choose data directory"), ui.lblDirName->text(), QFileDialog::ShowDirsOnly);
|
||||
if (!datadir.isEmpty()) {
|
||||
ui.lblDirName->setText(QDir::toNativeSeparators(datadir));
|
||||
}
|
||||
});
|
||||
|
||||
// Show the dialog
|
||||
QString datadir = "";
|
||||
bool useTor = false;
|
||||
if (d.exec() == QDialog::Accepted) {
|
||||
datadir = ui.lblDirName->text();
|
||||
useTor = ui.chkUseTor->isChecked();
|
||||
if (!ui.chkAllowInternet->isChecked()) {
|
||||
Settings::getInstance()->setAllowFetchPrices(false);
|
||||
Settings::getInstance()->setCheckForUpdates(false);
|
||||
}
|
||||
}
|
||||
|
||||
main->logger->write("Creating file " + confLocation);
|
||||
QDir().mkdir(fi.dir().absolutePath());
|
||||
|
||||
QFile file(confLocation);
|
||||
if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
|
||||
main->logger->write("Could not create zcash.conf, returning");
|
||||
return;
|
||||
}
|
||||
|
||||
QTextStream out(&file);
|
||||
|
||||
out << "server=1\n";
|
||||
out << "addnode=mainnet.z.cash\n";
|
||||
out << "rpcuser=zec-qt-wallet\n";
|
||||
out << "rpcpassword=" % randomPassword() << "\n";
|
||||
|
||||
// Fast sync override
|
||||
if (ui.chkFastSync->isChecked()) {
|
||||
out << "ibdskiptxverification=1\n";
|
||||
}
|
||||
|
||||
// Datadir override
|
||||
if (!datadir.isEmpty()) {
|
||||
out << "datadir=" % datadir % "\n";
|
||||
}
|
||||
|
||||
// Tor override
|
||||
if (useTor) {
|
||||
out << "proxy=127.0.0.1:9050\n";
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
// Now that zcash.conf exists, try to autoconnect again
|
||||
this->doAutoConnect();
|
||||
}
|
||||
|
||||
|
||||
void ConnectionLoader::downloadParams(std::function<void(void)> cb) {
|
||||
main->logger->write("Adding params to download queue");
|
||||
// Add all the files to the download queue
|
||||
downloadQueue = new QQueue<QUrl>();
|
||||
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);
|
||||
}
|
||||
|
||||
void ConnectionLoader::doNextDownload(std::function<void(void)> cb) {
|
||||
auto fnSaveFileName = [&] (QUrl url) {
|
||||
QString path = url.path();
|
||||
QString basename = QFileInfo(path).fileName();
|
||||
|
||||
return basename;
|
||||
};
|
||||
|
||||
if (downloadQueue->isEmpty()) {
|
||||
delete downloadQueue;
|
||||
client->deleteLater();
|
||||
|
||||
main->logger->write("All Downloads done");
|
||||
this->showInformation(QObject::tr("All Downloads Finished Successfully!"));
|
||||
cb();
|
||||
return;
|
||||
}
|
||||
|
||||
QUrl url = downloadQueue->dequeue();
|
||||
int filesRemaining = downloadQueue->size();
|
||||
|
||||
QString filename = fnSaveFileName(url);
|
||||
QString paramsDir = zcashParamsDir();
|
||||
|
||||
if (QFile(QDir(paramsDir).filePath(filename)).exists()) {
|
||||
main->logger->write(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)) {
|
||||
main->logger->write("Couldn't open " + currentOutput->fileName() + " for writing");
|
||||
this->showError(QObject::tr("Couldn't download params. Please check the help site for more info."));
|
||||
}
|
||||
main->logger->write("Downloading to " + filename);
|
||||
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 {
|
||||
speed /= 1024*1024;
|
||||
unit = "MB/s";
|
||||
}
|
||||
|
||||
this->showInformation(
|
||||
QObject::tr("Downloading ") % filename % (filesRemaining > 1 ? " ( +" % QString::number(filesRemaining) % QObject::tr(" more remaining )") : QString("")),
|
||||
QString::number(done/1024/1024, 'f', 0) % QObject::tr("MB of ") % QString::number(total/1024/1024, 'f', 0) + QObject::tr("MB at ") % QString::number(speed, 'f', 2) % unit);
|
||||
});
|
||||
|
||||
// Download Finished
|
||||
QObject::connect(currentDownload, &QNetworkReply::finished, [=] () {
|
||||
// Rename file
|
||||
main->logger->write("Finished downloading " + filename);
|
||||
currentOutput->rename(QDir(paramsDir).filePath(filename));
|
||||
|
||||
currentOutput->close();
|
||||
currentDownload->deleteLater();
|
||||
currentOutput->deleteLater();
|
||||
|
||||
if (currentDownload->error()) {
|
||||
main->logger->write("Downloading " + filename + " failed");
|
||||
this->showError(QObject::tr("Downloading ") + filename + QObject::tr(" 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() {
|
||||
if (!Settings::getInstance()->useEmbedded())
|
||||
return false;
|
||||
|
||||
main->logger->write("Trying to start embedded zcashd");
|
||||
|
||||
// Static because it needs to survive even after this method returns.
|
||||
static QString processStdErrOutput;
|
||||
|
||||
if (ezcashd != nullptr) {
|
||||
if (ezcashd->state() == QProcess::NotRunning) {
|
||||
if (!processStdErrOutput.isEmpty()) {
|
||||
QMessageBox::critical(main, QObject::tr("zcashd error"), "zcashd said: " + processStdErrOutput,
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, start zcashd
|
||||
QDir appPath(QCoreApplication::applicationDirPath());
|
||||
#ifdef Q_OS_LINUX
|
||||
auto zcashdProgram = appPath.absoluteFilePath("zqw-zcashd");
|
||||
if (!QFile(zcashdProgram).exists()) {
|
||||
zcashdProgram = appPath.absoluteFilePath("zcashd");
|
||||
}
|
||||
#elif defined(Q_OS_DARWIN)
|
||||
auto zcashdProgram = appPath.absoluteFilePath("zcashd");
|
||||
#else
|
||||
auto zcashdProgram = appPath.absoluteFilePath("zcashd.exe");
|
||||
#endif
|
||||
|
||||
if (!QFile(zcashdProgram).exists()) {
|
||||
qDebug() << "Can't find zcashd at " << zcashdProgram;
|
||||
main->logger->write("Can't find zcashd at " + zcashdProgram);
|
||||
return false;
|
||||
}
|
||||
|
||||
ezcashd = new QProcess(main);
|
||||
QObject::connect(ezcashd, &QProcess::started, [=] () {
|
||||
//qDebug() << "zcashd started";
|
||||
});
|
||||
|
||||
QObject::connect(ezcashd, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
|
||||
[=](int, QProcess::ExitStatus) {
|
||||
//qDebug() << "zcashd finished with code " << exitCode << "," << exitStatus;
|
||||
});
|
||||
|
||||
QObject::connect(ezcashd, &QProcess::errorOccurred, [&] (auto) {
|
||||
//qDebug() << "Couldn't start zcashd: " << error;
|
||||
});
|
||||
|
||||
QObject::connect(ezcashd, &QProcess::readyReadStandardError, [=]() {
|
||||
auto output = ezcashd->readAllStandardError();
|
||||
main->logger->write("zcashd stderr:" + output);
|
||||
processStdErrOutput.append(output);
|
||||
});
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
ezcashd->start(zcashdProgram);
|
||||
#elif defined(Q_OS_DARWIN)
|
||||
ezcashd->start(zcashdProgram);
|
||||
#else
|
||||
ezcashd->setWorkingDirectory(appPath.absolutePath());
|
||||
ezcashd->start("zcashd.exe");
|
||||
#endif // Q_OS_LINUX
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConnectionLoader::doManualConnect() {
|
||||
auto config = loadFromSettings();
|
||||
|
||||
if (!config) {
|
||||
// Nothing configured, show an error
|
||||
QString explanation = QString()
|
||||
% QObject::tr("A manual connection was requested, but the settings are not configured.\n\n"
|
||||
"Please set the host/port and user/password in the Edit->Settings menu.");
|
||||
|
||||
showError(explanation);
|
||||
doRPCSetConnection(nullptr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto connection = makeConnection(config);
|
||||
refreshZcashdState(connection, [=] () {
|
||||
QString explanation = QString()
|
||||
% QObject::tr("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) {
|
||||
rpc->setEZcashd(ezcashd);
|
||||
rpc->setConnection(conn);
|
||||
@@ -428,69 +127,7 @@ void ConnectionLoader::doRPCSetConnection(Connection* conn) {
|
||||
}
|
||||
|
||||
Connection* ConnectionLoader::makeConnection(std::shared_ptr<ConnectionConfig> config) {
|
||||
QNetworkAccessManager* client = new QNetworkAccessManager(main);
|
||||
|
||||
QUrl myurl;
|
||||
myurl.setScheme("http");
|
||||
myurl.setHost(config.get()->host);
|
||||
myurl.setPort(config.get()->port.toInt());
|
||||
|
||||
QNetworkRequest* request = new QNetworkRequest();
|
||||
request->setUrl(myurl);
|
||||
request->setHeader(QNetworkRequest::ContentTypeHeader, "text/plain");
|
||||
|
||||
QString userpass = config.get()->rpcuser % ":" % config.get()->rpcpassword;
|
||||
QString headerData = "Basic " + userpass.toLocal8Bit().toBase64();
|
||||
request->setRawHeader("Authorization", headerData.toLocal8Bit());
|
||||
|
||||
return new Connection(main, client, request, config);
|
||||
}
|
||||
|
||||
void ConnectionLoader::refreshZcashdState(Connection* connection, std::function<void(void)> refused) {
|
||||
json payload = {
|
||||
{"jsonrpc", "1.0"},
|
||||
{"id", "someid"},
|
||||
{"method", "getinfo"}
|
||||
};
|
||||
connection->doRPC(payload,
|
||||
[=] (auto) {
|
||||
// Success, hide the dialog if it was shown.
|
||||
d->hide();
|
||||
main->logger->write("zcashd is online.");
|
||||
this->doRPCSetConnection(connection);
|
||||
},
|
||||
[=] (auto reply, auto res) {
|
||||
// Failed, see what it is.
|
||||
auto err = reply->error();
|
||||
//qDebug() << err << ":" << QString::fromStdString(res.dump());
|
||||
|
||||
if (err == QNetworkReply::NetworkError::ConnectionRefusedError) {
|
||||
refused();
|
||||
} else if (err == QNetworkReply::NetworkError::AuthenticationRequiredError) {
|
||||
main->logger->write("Authentication failed");
|
||||
QString explanation = QString() %
|
||||
QObject::tr("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()) {
|
||||
// The server is loading, so just poll until it succeeds
|
||||
QString status = QString::fromStdString(res["error"]["message"]);
|
||||
{
|
||||
static int dots = 0;
|
||||
status = status.left(status.length() - 3) + QString(".").repeated(dots);
|
||||
dots++;
|
||||
if (dots > 3)
|
||||
dots = 0;
|
||||
}
|
||||
this->showInformation(QObject::tr("Your zcashd is starting up. Please wait."), status);
|
||||
main->logger->write("Waiting for zcashd to come online.");
|
||||
// Refresh after one second
|
||||
QTimer::singleShot(1000, [=]() { this->refreshZcashdState(connection, refused); });
|
||||
}
|
||||
}
|
||||
);
|
||||
return new Connection(main, config);
|
||||
}
|
||||
|
||||
// Update the UI with the status
|
||||
@@ -522,204 +159,42 @@ void ConnectionLoader::showError(QString explanation) {
|
||||
d->close();
|
||||
}
|
||||
|
||||
QString ConnectionLoader::locateZcashConfFile() {
|
||||
#ifdef Q_OS_LINUX
|
||||
auto confLocation = QStandardPaths::locate(QStandardPaths::HomeLocation, ".zcash/zcash.conf");
|
||||
#elif defined(Q_OS_DARWIN)
|
||||
auto confLocation = QStandardPaths::locate(QStandardPaths::HomeLocation, "Library/Application Support/Zcash/zcash.conf");
|
||||
#else
|
||||
auto confLocation = QStandardPaths::locate(QStandardPaths::AppDataLocation, "../../Zcash/zcash.conf");
|
||||
#endif
|
||||
void Executor::run() {
|
||||
const char* resp = litelib_execute(this->cmd.toStdString().c_str());
|
||||
QString reply = QString::fromStdString(resp);
|
||||
litelib_rust_free_string(resp);
|
||||
|
||||
main->logger->write("Found zcashconf at " + QDir::cleanPath(confLocation));
|
||||
return QDir::cleanPath(confLocation);
|
||||
auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false);
|
||||
|
||||
emit responseReady(parsed);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
main->logger->write("Found zcashconf at " + QDir::cleanPath(confLocation));
|
||||
return QDir::cleanPath(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(QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath("Library/Application Support/ZcashParams"));
|
||||
#else
|
||||
auto paramsLocation = QDir(QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("../../ZcashParams"));
|
||||
#endif
|
||||
|
||||
if (!paramsLocation.exists()) {
|
||||
main->logger->write("Creating params location at " + paramsLocation.absolutePath());
|
||||
QDir().mkpath(paramsLocation.absolutePath());
|
||||
}
|
||||
|
||||
main->logger->write("Found Zcash params directory at " + 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
|
||||
*/
|
||||
std::shared_ptr<ConnectionConfig> ConnectionLoader::autoDetectZcashConf() {
|
||||
auto confLocation = Settings::getInstance()->getZcashdConfLocation();
|
||||
|
||||
if (confLocation.isEmpty()) {
|
||||
confLocation = locateZcashConfFile();
|
||||
}
|
||||
|
||||
if (confLocation.isNull()) {
|
||||
// No Zcash file, just return with nothing
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QFile file(confLocation);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
qDebug() << file.errorString();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QTextStream in(&file);
|
||||
|
||||
auto zcashconf = new ConnectionConfig();
|
||||
zcashconf->host = "127.0.0.1";
|
||||
zcashconf->connType = ConnectionType::DetectedConfExternalZcashD;
|
||||
zcashconf->usingZcashConf = true;
|
||||
zcashconf->zcashDir = QFileInfo(confLocation).absoluteDir().absolutePath();
|
||||
zcashconf->zcashDaemon = false;
|
||||
|
||||
Settings::getInstance()->setUsingZcashConf(confLocation);
|
||||
|
||||
while (!in.atEnd()) {
|
||||
QString line = in.readLine();
|
||||
auto s = line.indexOf("=");
|
||||
QString name = line.left(s).trimmed().toLower();
|
||||
QString value = line.right(line.length() - s - 1).trimmed();
|
||||
|
||||
if (name == "rpcuser") {
|
||||
zcashconf->rpcuser = value;
|
||||
}
|
||||
if (name == "rpcpassword") {
|
||||
zcashconf->rpcpassword = value;
|
||||
}
|
||||
if (name == "rpcport") {
|
||||
zcashconf->port = value;
|
||||
}
|
||||
if (name == "daemon" && value == "1") {
|
||||
zcashconf->zcashDaemon = true;
|
||||
}
|
||||
if (name == "proxy") {
|
||||
zcashconf->proxy = value;
|
||||
}
|
||||
if (name == "testnet" &&
|
||||
value == "1" &&
|
||||
zcashconf->port.isEmpty()) {
|
||||
zcashconf->port = "18232";
|
||||
}
|
||||
if (name == "ibdskiptxverification" && value == "1") {
|
||||
zcashconf->skiptxverification = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 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";
|
||||
file.close();
|
||||
|
||||
// In addition to the zcash.conf file, also double check the params.
|
||||
|
||||
return std::shared_ptr<ConnectionConfig>(zcashconf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load connection settings from the UI, which indicates an unknown, external zcashd
|
||||
*/
|
||||
std::shared_ptr<ConnectionConfig> ConnectionLoader::loadFromSettings() {
|
||||
// Load from the QT Settings.
|
||||
QSettings s;
|
||||
|
||||
auto host = s.value("connection/host").toString();
|
||||
auto port = s.value("connection/port").toString();
|
||||
auto username = s.value("connection/rpcuser").toString();
|
||||
auto password = s.value("connection/rpcpassword").toString();
|
||||
|
||||
if (username.isEmpty() || password.isEmpty())
|
||||
return nullptr;
|
||||
|
||||
auto uiConfig = new ConnectionConfig{ host, port, username, password, false, false, false, "", "", ConnectionType::UISettingsZCashD};
|
||||
|
||||
return std::shared_ptr<ConnectionConfig>(uiConfig);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************************************************************
|
||||
* Connection Class
|
||||
************************************************************************************/
|
||||
Connection::Connection(MainWindow* m, QNetworkAccessManager* c, QNetworkRequest* r,
|
||||
std::shared_ptr<ConnectionConfig> conf) {
|
||||
this->restclient = c;
|
||||
this->request = r;
|
||||
Connection::Connection(MainWindow* m, std::shared_ptr<ConnectionConfig> conf) {
|
||||
this->config = conf;
|
||||
this->main = m;
|
||||
}
|
||||
|
||||
Connection::~Connection() {
|
||||
delete restclient;
|
||||
delete request;
|
||||
Connection::~Connection() {
|
||||
}
|
||||
|
||||
void Connection::doRPC(const json& payload, const std::function<void(json)>& cb,
|
||||
void Connection::doRPC(const QString cmd, const QString args, const std::function<void(json)>& cb,
|
||||
const std::function<void(QNetworkReply*, const json&)>& ne) {
|
||||
if (shutdownInProgress) {
|
||||
// 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) {
|
||||
// Ignoring callback because shutdown in progress
|
||||
return;
|
||||
}
|
||||
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
auto parsed = json::parse(reply->readAll(), nullptr, false);
|
||||
ne(reply, parsed);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
auto parsed = json::parse(reply->readAll(), nullptr, false);
|
||||
if (parsed.is_discarded()) {
|
||||
ne(reply, "Unknown error");
|
||||
}
|
||||
|
||||
cb(parsed["result"]);
|
||||
});
|
||||
// Create a runner.
|
||||
auto runner = new Executor(cmd, args);
|
||||
QObject::connect(runner, &Executor::responseReady, [=] (json resp) {
|
||||
cb(resp);
|
||||
})
|
||||
QThreadPool::globalInstance()->start(runner);
|
||||
}
|
||||
|
||||
void Connection::doRPCWithDefaultErrorHandling(const json& payload, const std::function<void(json)>& cb) {
|
||||
|
||||
@@ -9,24 +9,9 @@ using json = nlohmann::json;
|
||||
|
||||
class Controller;
|
||||
|
||||
enum ConnectionType {
|
||||
DetectedConfExternalZcashD = 1,
|
||||
UISettingsZCashD,
|
||||
InternalZcashD
|
||||
};
|
||||
|
||||
struct ConnectionConfig {
|
||||
QString host;
|
||||
QString port;
|
||||
QString rpcuser;
|
||||
QString rpcpassword;
|
||||
bool usingZcashConf;
|
||||
bool zcashDaemon;
|
||||
bool skiptxverification;
|
||||
QString zcashDir;
|
||||
QString proxy;
|
||||
|
||||
ConnectionType connType;
|
||||
QString server;
|
||||
bool dangerous;
|
||||
};
|
||||
|
||||
class Connection;
|
||||
@@ -81,17 +66,35 @@ private:
|
||||
QTime downloadTime;
|
||||
};
|
||||
|
||||
class Executor : public QRunnable {
|
||||
public:
|
||||
Executor(QString cmd, QString args) {
|
||||
this->cmd = cmd;
|
||||
this->args = args;
|
||||
};
|
||||
|
||||
~Executor() = default;
|
||||
bool autoDelete() const { return true; }
|
||||
|
||||
virtual void run();
|
||||
|
||||
signals:
|
||||
void responseReady(json);
|
||||
|
||||
private:
|
||||
QString cmd;
|
||||
QString args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a connection to a zcashd. It may even start a new zcashd if needed.
|
||||
* This is also a UI class, so it may show a dialog waiting for the connection.
|
||||
*/
|
||||
class Connection {
|
||||
class Connection : public QObject {
|
||||
public:
|
||||
Connection(MainWindow* m, QNetworkAccessManager* c, QNetworkRequest* r, std::shared_ptr<ConnectionConfig> conf);
|
||||
Connection(MainWindow* m, std::shared_ptr<ConnectionConfig> conf);
|
||||
~Connection();
|
||||
|
||||
QNetworkAccessManager* restclient;
|
||||
QNetworkRequest* request;
|
||||
std::shared_ptr<ConnectionConfig> config;
|
||||
MainWindow* main;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user