You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wowlet/src/utils/xmrig.cpp

117 lines
3.8 KiB

// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2020-2021, The Monero Project.
#include <QScreen>
#include <QDesktopWidget>
#include <QDesktopServices>
#include "utils/utils.h"
#include "utils/xmrig.h"
#include "mainwindow.h"
XmRig::XmRig(const QString &configDir, QObject *parent) :
QObject(parent),
m_statusTimer(new QTimer(this))
{
m_statusTimer->setInterval(5000);
connect(m_statusTimer, &QTimer::timeout, [this]{
if(mining_started && m_process.state() == QProcess::Running)
m_process.write("status\n");
});
}
void XmRig::prepare() {
m_process.setProcessChannelMode(QProcess::MergedChannels);
connect(&m_process, &QProcess::readyReadStandardOutput, this, &XmRig::handleProcessOutput);
connect(&m_process, &QProcess::errorOccurred, this, &XmRig::handleProcessError);
connect(&m_process, &QProcess::stateChanged, this, &XmRig::stateChanged);
}
void XmRig::stop() {
if(m_process.state() == QProcess::Running) {
#if defined(Q_OS_WIN)
m_process.kill(); // https://doc.qt.io/qt-5/qprocess.html#terminate
#else
m_process.terminate();
#endif
}
m_statusTimer->stop();
}
bool XmRig::start(const QString &path, int threads) {
m_ctx = MainWindow::getContext();
auto state = m_process.state();
if (state == QProcess::ProcessState::Running || state == QProcess::ProcessState::Starting) {
emit error("Can't start wownerod, already running or starting");
return false;
}
if(path.isEmpty()) {
emit error("wownerod path seems to be empty.");
return false;
}
if(!Utils::fileExists(path)) {
emit error(QString("Path to wownerod binary is invalid; file does not exist: %1").arg(path));
return false;
}
auto privateSpendKey = m_ctx->currentWallet->getSecretSpendKey();
QStringList arguments;
arguments << "--mining-threads" << QString::number(threads);
arguments << "--start-mining" << m_ctx->currentWallet->address(0, 0);
arguments << "--spendkey" << privateSpendKey;
QString cmd = QString("%1 %2").arg(path, arguments.join(" "));
cmd = cmd.replace(privateSpendKey, "[redacted]");
emit output(cmd.toUtf8());
m_process.start(path, arguments);
m_statusTimer->start();
return true;
}
void XmRig::stateChanged(QProcess::ProcessState state) {
if(state == QProcess::ProcessState::Running)
emit output("wownerod started");
else if (state == QProcess::ProcessState::NotRunning) {
emit output("wownerod stopped");
this->mining_started = false;
emit stopped();
}
}
void XmRig::handleProcessOutput() {
QByteArray data = m_process.readAllStandardOutput();
for(auto &line: data.split('\n')) {
if(line.indexOf("\tI") >= 20)
line = line.remove(0, line.indexOf("\tI") + 2);
if(line.trimmed().isEmpty() || line.startsWith("status")) continue;
if(line.contains("Mining started. Good luck"))
this->mining_started = true;
else if(line.contains("you won a block reward"))
emit blockReward();
else if(line.contains("mining at")) {
auto rate = line.remove(0, line.indexOf("mining at"));
rate = rate.remove(rate.indexOf(","), rate.length());
rate = rate.remove(0, 9);
rate = rate.trimmed();
emit hashrate(rate);
}
emit output(line);
}
}
void XmRig::handleProcessError(QProcess::ProcessError err) {
if (err == QProcess::ProcessError::Crashed)
emit error("wownerod crashed or killed");
else if (err == QProcess::ProcessError::FailedToStart) {
auto path = config()->get(Config::wownerodPath).toString();
emit error(QString("wownerod binary failed to start: %1").arg(path));
}
this->mining_started = false;
}