// SPDX-License-Identifier: BSD-3-Clause // SPDX-FileCopyrightText: 2020-2023 The Monero Project #include #include #include "utils/Utils.h" #include "utils/xmrig.h" #include "utils/TorManager.h" #include "appcontext.h" XmRig::XmRig(const QString &configDir, QObject *parent) : QObject(parent) { 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::onStateChanged); } void XmRig::stop() { qDebug() << m_process.processId(); if (m_process.state() == QProcess::Running) { #if defined(Q_OS_WIN) m_process.kill(); // https://doc.qt.io/qt-5/qprocess.html#terminate #elif defined(Q_OS_LINUX) if (m_elevated) { m_killProcess.start("pkexec", QStringList() << "kill" << QString::number(m_process.processId())); return; } #endif m_process.terminate(); } } void XmRig::start(const QString &path, int threads, const QString &address, const QString &username, const QString &password, bool tor, bool tls, bool elevated) { m_elevated = elevated; auto state = m_process.state(); if (state == QProcess::ProcessState::Running || state == QProcess::ProcessState::Starting) { emit error("Can't start XMRig, already running or starting"); return; } if (path.isEmpty()) { emit error("XmRig->Start path parameter missing."); return; } if (!Utils::fileExists(path)) { emit error(QString("Path to XMRig binary invalid; file does not exist: %1").arg(path)); return; } QStringList arguments; if (m_elevated) { arguments << path; } arguments << "-o" << address; arguments << "-a" << "rx/0"; arguments << "-u" << username; if (!password.isEmpty()) { arguments << "-p" << password; } arguments << "--no-color"; arguments << "-t" << QString::number(threads); if (tor) { QString host = config()->get(Config::socks5Host).toString(); QString port = config()->get(Config::socks5Port).toString(); if (!torManager()->isLocalTor()) { host = torManager()->featherTorHost; port = QString::number(torManager()->featherTorPort); } arguments << "-x" << QString("%1:%2").arg(host, port); } if (tls) { arguments << "--tls"; } arguments << "--donate-level" << "1"; QString cmd = QString("%1 %2").arg(path, arguments.join(" ")); emit output(cmd.toUtf8()); if (m_elevated) { m_process.start("pkexec", arguments); } else { m_process.start(path, arguments); } } void XmRig::onStateChanged(QProcess::ProcessState state) { emit stateChanged(state); if (state == QProcess::ProcessState::Running) { emit output("XMRig started"); } else if (state == QProcess::ProcessState::NotRunning) { emit output("XMRig stopped"); } } void XmRig::handleProcessOutput() { QByteArray _output = m_process.readAllStandardOutput(); if(_output.contains("miner") && _output.contains("speed")) { // detect hashrate auto str = Utils::barrayToString(_output); auto spl = str.mid(str.indexOf("speed")).split(" "); auto rate = spl.at(2) + "H/s"; qDebug() << "mining hashrate: " << rate; emit hashrate(rate); } emit output(_output); } void XmRig::handleProcessError(QProcess::ProcessError err) { if (err == QProcess::ProcessError::Crashed) emit error("XMRig crashed or killed"); else if (err == QProcess::ProcessError::FailedToStart) { auto path = config()->get(Config::xmrigPath).toString(); emit error(QString("XMRig binary failed to start: %1").arg(path)); } }