Browse Source

WIP to fix crazy bugs

old_duke
Duke Leto 4 years ago
parent
commit
4eea97a04e
  1. 63
      src/connection.cpp
  2. 23
      src/connection.h
  3. 10
      src/mainwindow.cpp
  4. 132
      src/rpc.cpp
  5. 10
      src/rpc.h

63
src/connection.cpp

@ -1,5 +1,5 @@
// Copyright 2019-2020 The Hush developers
// GPLv3
// Released under the GPLv3
#include "connection.h"
#include "mainwindow.h"
#include "settings.h"
@ -44,12 +44,14 @@ ConnectionLoader::~ConnectionLoader() {
}
void ConnectionLoader::loadConnection() {
qDebug() << __func__;
QTimer::singleShot(1, [=]() { this->doAutoConnect(); });
if (!Settings::getInstance()->isHeadless())
d->exec();
}
void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
qDebug() << __func__;
// Priority 1: Ensure all params are present.
if (!verifyParams()) {
downloadParams([=]() { this->doAutoConnect(); });
@ -63,7 +65,7 @@ void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
if (config.get() != nullptr) {
auto connection = makeConnection(config);
refreshZcashdState(connection, [=] () {
refreshHushdState(connection, [=] () {
// Refused connection. So try and start embedded zcashd
if (Settings::getInstance()->useEmbedded()) {
if (tryEzcashdStart) {
@ -84,11 +86,11 @@ void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
// 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
main->logger->write("Unknown problem while trying to start hushd!");
QTimer::singleShot(2000, [=]() { doAutoConnect(/* don't attempt to start ezcashd */ false); });
QTimer::singleShot(2000, [=]() { doAutoConnect(/* don't attempt to start ehushd */ false); });
}
}
} else {
// We tried to start ezcashd previously, and it didn't work. So, show the error.
// We tried to start ehushd previously, and it didn't work. So, show the error.
main->logger->write("Couldn't start embedded hushd for unknown reason");
QString explanation;
if (config->zcashDaemon) {
@ -100,7 +102,7 @@ void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
explanation = QString() % QObject::tr("Couldn't start the embedded hushd.\n\n"
"Please try restarting.\n\nIf you previously started hushd with custom arguments, you might need to reset HUSH3.conf.\n\n"
"If all else fails, please run hushd manually.") %
(ezcashd ? QObject::tr("The process returned") + ":\n\n" % ezcashd->errorString() : QString(""));
(ehushd ? QObject::tr("The process returned") + ":\n\n" % ehushd->errorString() : QString(""));
}
this->showError(explanation);
@ -116,6 +118,7 @@ void ConnectionLoader::doAutoConnect(bool tryEzcashdStart) {
} else {
if (Settings::getInstance()->useEmbedded()) {
// HUSH3.conf was not found, so create one
qDebug() << "Creating HUSH3.conf";
createZcashConf();
} else {
// Fall back to manual connect
@ -217,6 +220,9 @@ void ConnectionLoader::createZcashConf() {
// Consolidation is now defaulted to ON for new wallets
out << "consolidation=1\n";
// Deletetx has some perfomance issues for large wallets, still in testing
//out << "deletetx=1\n";
if (!datadir.isEmpty()) {
out << "datadir=" % datadir % "\n";
}
@ -225,6 +231,7 @@ void ConnectionLoader::createZcashConf() {
}
file.close();
qDebug() << "HUSH3.conf finished being written to disk";
// Now that HUSH3.conf exists, try to autoconnect again
this->doAutoConnect();
@ -232,14 +239,14 @@ void ConnectionLoader::createZcashConf() {
void ConnectionLoader::downloadParams(std::function<void(void)> cb) {
main->logger->write("Adding params to download queue");
main->logger->write("Adding params to download queue, wtfbbqlol?");
// Add all the files to the download queue
downloadQueue = new QQueue<QUrl>();
client = new QNetworkAccessManager(main);
//Currently we fallback to this in rare edgecases, it's not normally executed
downloadQueue->enqueue(QUrl("https://z.cash/downloads/sapling-output.params"));
downloadQueue->enqueue(QUrl("https://z.cash/downloads/sapling-spend.params"));
downloadQueue->enqueue(QUrl("https://github.com/MyHush/hush3/raw/master/sapling-output.params"));
downloadQueue->enqueue(QUrl("https://github.com/MyHush/hush3/raw/master/sapling-spend.params"));
doNextDownload(cb);
}
@ -343,8 +350,8 @@ bool ConnectionLoader::startEmbeddedZcashd() {
// Static because it needs to survive even after this method returns.
static QString processStdErrOutput;
if (ezcashd != nullptr) {
if (ezcashd->state() == QProcess::NotRunning) {
if (ehushd != nullptr) {
if (ehushd->state() == QProcess::NotRunning) {
if (!processStdErrOutput.isEmpty()) {
QMessageBox::critical(main, QObject::tr("hushd error"), "hushd said: " + processStdErrOutput,
QMessageBox::Ok);
@ -372,23 +379,23 @@ bool ConnectionLoader::startEmbeddedZcashd() {
main->logger->write("Found hushd at " + hushdProgram);
}
ezcashd = std::shared_ptr<QProcess>(new QProcess(main));
QObject::connect(ezcashd.get(), &QProcess::started, [=] () {
ehushd = std::shared_ptr<QProcess>(new QProcess(main));
QObject::connect(ehushd.get(), &QProcess::started, [=] () {
qDebug() << "Embedded hushd started via " << hushdProgram;
});
QObject::connect(ezcashd.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
QObject::connect(ehushd.get(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
[=](int exitCode, QProcess::ExitStatus exitStatus) {
qDebug() << "hushd finished with code " << exitCode << "," << exitStatus;
});
QObject::connect(ezcashd.get(), &QProcess::errorOccurred, [&] (QProcess::ProcessError error) {
QObject::connect(ehushd.get(), &QProcess::errorOccurred, [&] (QProcess::ProcessError error) {
qDebug() << "Couldn't start hushd at " << hushdProgram << ":" << error;
});
std::weak_ptr<QProcess> weak_obj(ezcashd);
std::weak_ptr<QProcess> weak_obj(ehushd);
auto ptr_main(main);
QObject::connect(ezcashd.get(), &QProcess::readyReadStandardError, [weak_obj, ptr_main]() {
QObject::connect(ehushd.get(), &QProcess::readyReadStandardError, [weak_obj, ptr_main]() {
auto output = weak_obj.lock()->readAllStandardError();
ptr_main->logger->write("hushd stderr:" + output);
processStdErrOutput.append(output);
@ -402,18 +409,18 @@ bool ConnectionLoader::startEmbeddedZcashd() {
#ifdef Q_OS_LINUX
qDebug() << "Starting on Linux: " + hushdProgram + " " + params;
ezcashd->start(hushdProgram, arguments);
ehushd->start(hushdProgram, arguments);
#elif defined(Q_OS_DARWIN)
qDebug() << "Starting on Darwin: " + hushdProgram + " " + params;
ezcashd->start(hushdProgram, arguments);
ehushd->start(hushdProgram, arguments);
#elif defined(Q_OS_WIN64)
qDebug() << "Starting on Win64: " + hushdProgram + " " + params;
ezcashd->setWorkingDirectory(appPath.absolutePath());
ezcashd->start(hushdProgram, arguments);
ehushd->setWorkingDirectory(appPath.absolutePath());
ehushd->start(hushdProgram, arguments);
#else
qDebug() << "Starting on Unknown OS(!): " + hushdProgram + " " + params;
ezcashd->setWorkingDirectory(appPath.absolutePath());
ezcashd->start(hushdProgram, arguments);
ehushd->setWorkingDirectory(appPath.absolutePath());
ehushd->start(hushdProgram, arguments);
#endif // Q_OS_LINUX
main->logger->write("Started via " + hushdProgram + " " + params);
@ -436,7 +443,7 @@ void ConnectionLoader::doManualConnect() {
}
auto connection = makeConnection(config);
refreshZcashdState(connection, [=] () {
refreshHushdState(connection, [=] () {
QString explanation = QString()
% QObject::tr("Could not connect to hushd configured in settings.\n\n"
"Please set the host/port and user/password in the Edit->Settings menu.");
@ -475,14 +482,10 @@ Connection* ConnectionLoader::makeConnection(std::shared_ptr<ConnectionConfig> c
return new Connection(main, client, request, config);
}
void ConnectionLoader::refreshZcashdState(Connection* connection, std::function<void(void)> refused) {
void ConnectionLoader::refreshHushdState(Connection* connection, std::function<void(void)> refused) {
main->logger->write("refreshing state");
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
{"method", "getinfo"}
};
auto payload = rpc->makePayload("getinfo");
connection->doRPC(payload,
[=] (auto) {
// Success
@ -518,7 +521,7 @@ void ConnectionLoader::refreshZcashdState(Connection* connection, std::function<
this->showInformation(QObject::tr("Your hushd is starting up. Please wait."), status);
main->logger->write("Waiting for hushd to come online.");
// Refresh after one second
QTimer::singleShot(1000, [=]() { this->refreshZcashdState(connection, refused); });
QTimer::singleShot(1000, [=]() { this->refreshHushdState(connection, refused); });
}
}
);

23
src/connection.h

@ -45,7 +45,7 @@ private:
Connection* makeConnection(std::shared_ptr<ConnectionConfig> config);
void doAutoConnect(bool tryEzcashdStart = true);
void doAutoConnect(bool tryEhushdStart = true);
void doManualConnect();
void createZcashConf();
@ -58,14 +58,14 @@ private:
void doNextDownload(std::function<void(void)> cb);
bool startEmbeddedZcashd();
void refreshZcashdState(Connection* connection, std::function<void(void)> refused);
void refreshHushdState(Connection* connection, std::function<void(void)> refused);
void showError(QString explanation);
void showInformation(QString info, QString detail = "");
void doRPCSetConnection(Connection* conn);
std::shared_ptr<QProcess> ezcashd;
std::shared_ptr<QProcess> ehushd;
QDialog* d;
Ui_ConnectionDialog* connD;
@ -82,7 +82,7 @@ private:
};
/**
* Represents a connection to a zcashd. It may even start a new zcashd if needed.
* Represents a connection to a hushd. It may even start a new hushd if needed.
* This is also a UI class, so it may show a dialog waiting for the connection.
*/
class Connection {
@ -119,6 +119,7 @@ public:
static QMap<QString, bool> inProgress;
QString method = payloadGenerator(payloads[0])["method"].toString();
qDebug() << __func__ << "(" << method << ") totalSize=" << totalSize << " at " << QDateTime::currentSecsSinceEpoch();
//if (inProgress.value(method, false)) {
// qDebug() << "In progress batch, skipping";
@ -126,6 +127,7 @@ public:
//}
for (auto item: payloads) {
qDebug() << __func__ << ": payload " << item;
QJsonValue payload = payloadGenerator(item);
inProgress[method] = true;
@ -137,22 +139,25 @@ public:
QObject::connect(reply, &QNetworkReply::finished, [=] {
reply->deleteLater();
if (shutdownInProgress) {
// Ignoring callback because shutdown in progress
qDebug() << __func__ << ": Ignoring callback because shutdown in progress";
return;
}
auto all = reply->readAll();
auto parsed = QJsonDocument::fromJson(all);
if (reply->error() != QNetworkReply::NoError) {
qDebug() << parsed.toJson();
qDebug() << "Error JSON response: " << parsed.toJson();
qDebug() << reply->errorString();
(*responses)[item] = {}; // Empty object
} else {
if (parsed.isEmpty()) {
qDebug() << __func__ << ": got empty response";
(*responses)[item] = {}; // Empty object
} else {
qDebug() << "Got network reply from RPC " << method << "(" << payload << ")" << " of " << parsed["result"].toString().size() << " bytes";
(*responses)[item] = parsed["result"];
}
}
@ -162,14 +167,18 @@ public:
auto waitTimer = new QTimer(main);
QObject::connect(waitTimer, &QTimer::timeout, [=]() {
if (shutdownInProgress) {
qDebug() << "Shutdown in progress, aborting";
waitTimer->stop();
waitTimer->deleteLater();
return;
}
//qDebug() << ".";
// If all responses have arrived, return
if (responses->size() == totalSize) {
qDebug() << __func__ << ": stopping timer";
waitTimer->stop();
cb(responses);
@ -178,7 +187,9 @@ public:
waitTimer->deleteLater();
}
});
qDebug() << __func__ << ": starting timer"<< QDateTime::currentSecsSinceEpoch();
waitTimer->start(100);
qDebug() << __func__ << ": finished at " << QDateTime::currentSecsSinceEpoch();
}
private:

10
src/mainwindow.cpp

@ -118,9 +118,10 @@ MainWindow::MainWindow(QWidget *parent) :
// Initialize to the balances tab
ui->tabWidget->setCurrentIndex(0);
setupSendTab();
setupTransactionsTab();
setupReceiveTab();
setupTransactionsTab();
setupSendTab();
setupBalancesTab();
setupMarketTab();
//setupChatTab();
@ -253,6 +254,7 @@ void MainWindow::setupStatusBar() {
}
menu.addAction("Refresh", [=]() {
qDebug() << "Manual refresh";
rpc->refresh(true);
});
QPoint gpos(mapToGlobal(pos).x(), mapToGlobal(pos).y() + this->height() - ui->statusBar->height());
@ -1180,8 +1182,10 @@ void MainWindow::setupMarketTab() {
}
void MainWindow::setupTransactionsTab() {
qDebug() << __func__;
// Double click opens up memo if one exists
QObject::connect(ui->transactionsTable, &QTableView::doubleClicked, [=] (auto index) {
qDebug() << "Tx double clicked, showing memo";
auto txModel = dynamic_cast<TxTableModel *>(ui->transactionsTable->model());
QString memo = txModel->getMemo(index.row());
@ -1294,6 +1298,7 @@ void MainWindow::setupTransactionsTab() {
void MainWindow::addNewZaddr() {
rpc->newZaddr( [=] (QJsonValue reply) {
QString addr = reply.toString();
qDebug() << __func__ << ": created new zaddr " << addr;
// Make sure the RPC class reloads the z-addrs for future use
rpc->refreshAddresses();
@ -1335,6 +1340,7 @@ std::function<void(bool)> MainWindow::addZAddrsToComboList(bool sapling) {
}
void MainWindow::setupReceiveTab() {
qDebug() << __func__;
auto addNewTAddr = [=] () {
rpc->newTaddr([=] (QJsonValue reply) {
qDebug() << "New addr button clicked";

132
src/rpc.cpp

@ -11,6 +11,7 @@
RPC::RPC(MainWindow* main) {
auto cl = new ConnectionLoader(main, this);
qDebug() << "ConnectionLoader created";
// Execute the load connection async, so we can set up the rest of RPC properly.
QTimer::singleShot(1, [=]() { cl->loadConnection(); });
@ -26,26 +27,30 @@ RPC::RPC(MainWindow* main) {
transactionsTableModel = new TxTableModel(ui->transactionsTable);
main->ui->transactionsTable->setModel(transactionsTableModel);
main->ui->transactionsTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::Stretch);
qDebug() << "Created transationsTableModel";
// Set up timer to refresh Price
priceTimer = new QTimer(main);
QObject::connect(priceTimer, &QTimer::timeout, [=]() {
qDebug() << "Refreshing price at " << QDateTime::currentSecsSinceEpoch();
refreshPrice();
});
priceTimer->start(Settings::priceRefreshSpeed); // Every hour
qDebug() << "Starting price timer with speed=" << Settings::priceRefreshSpeed;
priceTimer->start(Settings::priceRefreshSpeed);
// Set up a timer to refresh the UI every few seconds
timer = new QTimer(main);
QObject::connect(timer, &QTimer::timeout, [=]() {
qDebug() << "Refreshing main UI";
qDebug() << "Refreshing main UI with timer at " << QDateTime::currentSecsSinceEpoch();
refresh();
});
qDebug() << "Starting main UI timer with speed=" << Settings::updateSpeed;
timer->start(Settings::updateSpeed);
// Set up the timer to watch for tx status
txTimer = new QTimer(main);
QObject::connect(txTimer, &QTimer::timeout, [=]() {
qDebug() << "Watching tx status";
qDebug() << "Watching tx status at " << QDateTime::currentSecsSinceEpoch();
watchTxStatus();
});
// Start at normal updateSpeed. When an operation is pending, this will change to quickUpdateSpeed
@ -237,6 +242,7 @@ void RPC::getTransactions(const std::function<void(QJsonValue)>& cb) {
void RPC::sendZTransaction(QJsonValue params, const std::function<void(QJsonValue)>& cb,
const std::function<void(QString)>& err) {
qDebug() << __func__ << " at " << QDateTime::currentSecsSinceEpoch();
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "someid"},
@ -343,6 +349,7 @@ void RPC::getAllPrivKeys(const std::function<void(QList<QPair<QString, QString>>
// Build the RPC JSON Parameters for this tx
void RPC::fillTxJsonParams(QJsonArray& params, Tx tx) {
qDebug() << __func__;
Q_ASSERT(QJsonValue(params).isArray());
@ -379,6 +386,7 @@ void RPC::fillTxJsonParams(QJsonArray& params, Tx tx) {
void RPC::noConnection() {
qDebug() << "No connection!!!";
QIcon i = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical);
main->statusIcon->setPixmap(i.pixmap(16, 16));
main->statusIcon->setToolTip("");
@ -411,24 +419,36 @@ void RPC::noConnection() {
ui->inputsCombo->clear();
}
// Refresh received z txs by calling z_listreceivedbyaddress/gettransaction
// Refresh received z txs by calling z_listreceivedbyaddress
void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
qDebug() << __func__ << " at " << QDateTime::currentSecsSinceEpoch();
if (conn == nullptr)
return noConnection();
// We'll only refresh the received Z txs if settings allows us.
if (!Settings::getInstance()->getSaveZtxs()) {
qDebug() << "Not saving sent ztx's as per settings";
QList<TransactionItem> emptylist;
transactionsTableModel->addZRecvData(emptylist);
return;
}
// This method is complicated because z_listreceivedbyaddress only returns the txid, and
// we have to make a follow up call to gettransaction to get details of that transaction.
// Additionally, it has to be done in batches, because there are multiple z-Addresses,
// It has to be done in batches, because there are multiple z-Addresses,
// and each z-Addr can have multiple received txs.
// 1. For each z-Addr, get list of received txs
/*
{
"txid": "deadbeef",
"amount": 420.69000000,
"memo": "...",
"memoStr": "",
"outindex": 0,
"rawconfirmations": 27793,
"confirmations": 27793,
"change": false
}
*/
conn->doBatchRPC<QString>(zaddrs,
[=] (QString zaddr) {
QJsonObject payload = {
@ -441,12 +461,15 @@ void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
return payload;
},
[=] (QMap<QString, QJsonValue>* zaddrTxids) {
qDebug() << __func__ << ": processing z_listreceivedbyaddress JSON at " << QDateTime::currentSecsSinceEpoch();
// Process all txids, removing duplicates. This can happen if the same address
// appears multiple times in a single tx's outputs.
QSet<QString> txids;
QMap<QString, QString> memos;
for (auto it = zaddrTxids->constBegin(); it != zaddrTxids->constEnd(); it++) {
auto zaddr = it.key();
auto zaddr = it.key();
qint64 numTx = 0;
qDebug() << __func__ << ": processing tx's of " << zaddr << " at " << QDateTime::currentSecsSinceEpoch();
for (const auto& i : it.value().toArray()) {
// Mark the address as used
usedAddresses->insert(zaddr, true);
@ -464,63 +487,48 @@ void RPC::refreshReceivedZTrans(QList<QString> zaddrs) {
if (!memo.trimmed().isEmpty())
memos[zaddr + txid] = memo;
}
}
}
}
// 2. For all txids, go and get the details of that txid.
conn->doBatchRPC<QString>(txids.toList(),
[=] (QString txid) {
QJsonObject payload = {
{"jsonrpc", "1.0"},
{"id", "gettx"},
{"method", "gettransaction"},
{"params", QJsonArray {txid}}
};
return payload;
},
[=] (QMap<QString, QJsonValue>* txidDetails) {
QList<TransactionItem> txdata;
// Fill in other data
QList<TransactionItem> txdata;
// Combine them both together. For every zAddr's txid, get the amount, fee, confirmations and time
for (auto it = zaddrTxids->constBegin(); it != zaddrTxids->constEnd(); it++) {
for (const auto& i : it.value().toArray()) {
for (const auto& j : it.value().toArray()) {
numTx++;
// Filter out change txs
if (i.toObject()["change"].toBool())
if (j.toObject()["change"].toBool()) {
//qDebug() << __func__ << ": filtered change";
continue;
}
auto zaddr = it.key();
auto txid = i.toObject()["txid"].toString();
auto txid = j.toObject()["txid"].toString();
// Lookup txid in the map
auto txidInfo = txidDetails->value(txid);
auto txidInfo = zaddrTxids->find(txid);
qint64 timestamp;
if (!txidInfo.toObject()["time"].isUndefined()) {
timestamp = txidInfo.toObject()["time"].toInt();
if (!txidInfo->toObject()["time"].isUndefined()) {
timestamp = txidInfo->toObject()["time"].toInt();
} else {
timestamp = txidInfo.toObject()["blocktime"].toInt();
timestamp = txidInfo->toObject()["blocktime"].toInt();
}
auto amount = i.toObject()["amount"].toDouble();
auto confirmations = (unsigned long)txidInfo["confirmations"].toInt();
auto amount = j.toObject()["amount"].toDouble();
//auto confirmations = (unsigned long)txidInfo["confirmations"].toInt();
auto confirmations = (unsigned long)txidInfo->toObject()["confirmations"].toInt();
TransactionItem tx{ QString("receive"), timestamp, zaddr, txid, amount,
confirmations, "", memos.value(zaddr + txid, "") };
//qDebug() << __func__ << ": Adding " << txid << " at time=" << timestamp << " with " << confirmations << " confs";
TransactionItem tx{ QString("receive"), timestamp, zaddr, txid, amount, confirmations, "", memos.value(zaddr + txid, "") };
txdata.push_front(tx);
if(numTx % 1000 == 0) {
qDebug() << "z_listreceivedbyaddress: Processed " << numTx << " transactions for " << zaddr;
}
}
}
transactionsTableModel->addZRecvData(txdata);
// Cleanup both responses;
delete zaddrTxids;
delete txidDetails;
}
);
qDebug() << __func__ << ": Updating transactionsTableModel with numTx=" << numTx;
transactionsTableModel->addZRecvData(txdata);
}
}
}
}
);
delete zaddrTxids;
delete txidDetails;
}
/// This will refresh all the balance data from hushd
@ -583,6 +591,7 @@ void RPC::getInfoThenRefresh(bool force) {
if ( force || (curBlock != lastBlock) ) {
// Something changed, so refresh everything.
qDebug() << "Something changed, time to refresh";
lastBlock = curBlock;
refreshBalances();
@ -731,6 +740,7 @@ void RPC::getInfoThenRefresh(bool force) {
}
void RPC::refreshAddresses() {
qDebug() << __func__;
if (conn == nullptr)
return noConnection();
@ -777,6 +787,7 @@ void RPC::updateUI(bool anyUnconfirmed) {
// Function to process reply of the listunspent and z_listunspent API calls, used below.
bool RPC::processUnspent(const QJsonValue& reply, QMap<QString, double>* balancesMap, QList<UnspentOutput>* newUtxos) {
qDebug() << __func__;
bool anyUnconfirmed = false;
for (const auto& it : reply.toArray()) {
QString qsAddr = it.toObject()["address"].toString();
@ -796,6 +807,7 @@ bool RPC::processUnspent(const QJsonValue& reply, QMap<QString, double>* balance
};
void RPC::refreshBalances() {
qDebug() << __func__;
if (conn == nullptr)
return noConnection();
@ -844,9 +856,11 @@ void RPC::refreshBalances() {
main->balancesReady();
});
});
qDebug() << __func__ << ": finished";
}
void RPC::refreshTransactions() {
qDebug() << __func__;
if (conn == nullptr)
return noConnection();
@ -876,6 +890,7 @@ void RPC::refreshTransactions() {
}
// Update model data, which updates the table view
qDebug() << __func__ << ": updating transactionTableModel tdata";
transactionsTableModel->addTData(txdata);
});
}
@ -974,7 +989,7 @@ void RPC::watchTxStatus() {
// Make an RPC to load pending operation statues
conn->doRPCIgnoreError(makePayload("z_getoperationstatus"), [=] (const QJsonValue& reply) {
qDebug() << "Got reply from z_getoperationstatus with " << reply.toArray().size() << " items";
qDebug() << "Got reply from z_getoperationstatus with " << reply.toArray().size() << " items:" << reply.toString();
// conn->doRPCIgnoreError(payload, [=] (const json& reply) {
// There's an array for each item in the status
for (const auto& it : reply.toArray()) {
@ -990,10 +1005,12 @@ void RPC::watchTxStatus() {
if (status == "success") {
auto txid = it.toObject()["result"].toObject()["txid"].toString();
qDebug() << "Found opid " << id << " with status=success and txid=" << txid;
SentTxStore::addToSentTx(watchingOps[id].tx, txid);
auto wtx = watchingOps[id];
watchingOps.remove(id);
qDebug() << "Removed opid " << id;
wtx.completed(id, txid);
qDebug() << "opid "<< id << " for " << txid << " started at "<<QString::number((unsigned int)it.toObject()["creation_time"].toInt()) << " took " << QString::number((double)it.toObject()["execution_secs"].toDouble()) << " seconds";
@ -1001,11 +1018,12 @@ void RPC::watchTxStatus() {
// Refresh balances to show unconfirmed balances
refresh(true);
} else if (status == "failed") {
qDebug() << "opid "<< id << " started at "<<QString::number((unsigned int)it.toObject()["creation_time"].toInt()) << " FAILED!";
// If it failed, then we'll actually show a warning.
auto errorMsg = it.toObject()["error"].toObject()["message"].toString();
auto wtx = watchingOps[id];
auto wtx = watchingOps[id];
watchingOps.remove(id);
qDebug() << "Removed opid " << id;
wtx.error(id, errorMsg);
}
}
@ -1215,7 +1233,7 @@ void RPC::refreshPrice() {
void RPC::shutdownHushd() {
// Shutdown embedded hushd if it was started
if (ezcashd == nullptr || ezcashd->processId() == 0 || conn == nullptr) {
if (ehushd == nullptr || ehushd->processId() == 0 || conn == nullptr) {
// No hushd running internally, just return
return;
}
@ -1254,8 +1272,8 @@ void RPC::shutdownHushd() {
QObject::connect(&waiter, &QTimer::timeout, [&] () {
waitCount++;
if ((ezcashd->atEnd() && ezcashd->processId() == 0) ||
ezcashd->state() == QProcess::NotRunning ||
if ((ehushd->atEnd() && ehushd->processId() == 0) ||
ehushd->state() == QProcess::NotRunning ||
waitCount > 30 ||
conn->config->zcashDaemon) { // If hushd is daemon, then we don't have to do anything else
qDebug() << "Ended";

10
src/rpc.h

@ -38,7 +38,7 @@ public:
~RPC();
void setConnection(Connection* c);
const QProcess* getEZcashD() { return ezcashd.get(); }
const QProcess* getEZcashD() { return ehushd.get(); }
void refresh(bool force = false);
@ -79,7 +79,9 @@ public:
void shutdownHushd();
void noConnection();
bool isEmbedded() { return ezcashd != nullptr; }
bool isEmbedded() { return ehushd != nullptr; }
QJsonValue makePayload(QString method, QString params);
QJsonValue makePayload(QString method);
QString getDefaultSaplingAddress();
QString getDefaultTAddress();
@ -102,8 +104,6 @@ private:
void getInfoThenRefresh(bool force);
void getBalance(const std::function<void(QJsonValue)>& cb);
QJsonValue makePayload(QString method, QString params);
QJsonValue makePayload(QString method);
void getTransparentUnspent (const std::function<void(QJsonValue)>& cb);
void getZUnspent (const std::function<void(QJsonValue)>& cb);
@ -112,7 +112,7 @@ private:
void getTAddresses (const std::function<void(QJsonValue)>& cb);
Connection* conn = nullptr;
std::shared_ptr<QProcess> ezcashd = nullptr;
std::shared_ptr<QProcess> ehushd = nullptr;
QList<UnspentOutput>* utxos = nullptr;
QMap<QString, double>* allBalances = nullptr;

Loading…
Cancel
Save