XMRigCC 2.0 (#263)

# 2.0.0
**Thx to @xmrig and @SChernykh awesome work!**
* Full Rebase on XMRig 3.1.1 
     * randomX/wow/XL
     * NUMA support
     * flexible multi algorithm configuration
     * unlimited switching between incompatible algorithms at runtime
* Argon2, UPX2 (Nice hashrate improvement) and CN-Conceal support integrated like in previous version
* 5-10% Hashrate improvement on ARMv8 CPUs when mining CN based algos compared to stock xmrig
* Fully compatible to XMRigCCServer 1.9.5 no server upgrade needed!
**New XMRigCCServer will be released soon with new features**
This commit is contained in:
Ben Gräf 2019-09-01 08:02:09 +02:00 committed by GitHub
parent 7d7a3a71f8
commit b8fe729b52
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
645 changed files with 85475 additions and 63443 deletions

View file

@ -1,6 +1,5 @@
/* XMRigCC
* Copyright 2017- BenDr0id <ben@graef.in>
*
* Copyright 2017- BenDr0id <https://github.com/BenDr0id>, <ben@graef.in>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -21,14 +20,21 @@
#include <fstream>
#include <3rdparty/rapidjson/stringbuffer.h>
#include <3rdparty/rapidjson/prettywriter.h>
#include <crypto/common/VirtualMemory.h>
#include "version.h"
#include "api/NetworkState.h"
#include "backend/cpu/Cpu.h"
#include "base/tools/Timer.h"
#include "base/tools/Chrono.h"
#include "base/kernel/Base.h"
#include "base/kernel/Platform.h"
#include "base/cc/interfaces/IClientStatusListener.h"
#include "base/cc/interfaces/ICommandListener.h"
#include "CCClient.h"
#include "App.h"
#include "Cpu.h"
#include "ControlCommand.h"
#include "version.h"
#ifdef TYPE_AMD_GPU
#include "common/log/Log.h"
@ -36,16 +42,11 @@
#include "common/Platform.h"
#include "core/Config.h"
#else
#include "Mem.h"
#include "log/Log.h"
#include "log/RemoteLog.h"
#include "Platform.h"
#include "api/NetworkState.h"
#include "core/config/Config.h"
#include "base/io/log/Log.h"
#include "base/io/log/backends/RemoteLog.h"
#endif
#include "workers/Workers.h"
#include "workers/Hashrate.h"
#if _WIN32
# include "winsock2.h"
#else
@ -55,24 +56,60 @@
#endif
CCClient* CCClient::m_self = nullptr;
uv_mutex_t CCClient::m_mutex;
#ifdef TYPE_AMD_GPU
CCClient::CCClient(xmrig::Config* config, uv_async_t* async)
xmrig::CCClient::CCClient(xmrig::Config* config, uv_async_t* async)
#else
CCClient::CCClient(Options* config, uv_async_t* async)
xmrig::CCClient::CCClient(Base *base)
#endif
: m_config(config),
m_async(async)
: m_base(base),
m_startTime(Chrono::currentMSecsSinceEpoch()),
m_configPublishedOnStart(false),
m_timer(nullptr)
{
uv_mutex_init(&m_mutex);
base->addListener(this);
m_self = this;
m_timer = new Timer(this);
}
xmrig::CCClient::~CCClient()
{
delete m_timer;
}
void xmrig::CCClient::start()
{
LOG_DEBUG("CCClient::start");
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CSI "1;%dm%s",
"CC Server",
(m_base->config()->ccClient().useTLS() ? 32 : 36),
m_base->config()->ccClient().url()
);
updateAuthorization();
updateClientInfo();
m_timer->start(static_cast<uint64_t>(m_base->config()->ccClient().updateInterval()*1000),
static_cast<uint64_t>(m_base->config()->ccClient().updateInterval()*1000));
}
void xmrig::CCClient::updateAuthorization()
{
LOG_DEBUG("CCClient::updateAuthorization");
if (m_base->config()->ccClient().token() != nullptr) {
m_authorization = std::string("Bearer ") + m_base->config()->ccClient().token();
}
}
void xmrig::CCClient::updateClientInfo()
{
LOG_DEBUG("CCClient::updateClientInfo");
std::string clientId;
if (config->ccWorkerId()) {
clientId =m_self->m_config->ccWorkerId();
if (m_base->config()->ccClient().workerId()) {
clientId = m_base->config()->ccClient().workerId();
} else {
char hostname[128];
memset(hostname, 0, sizeof(hostname));
@ -80,90 +117,70 @@ CCClient::CCClient(Options* config, uv_async_t* async)
clientId = std::string(hostname);
}
auto cpuInfo = xmrig::Cpu::info();
m_clientStatus.setClientId(clientId);
m_clientStatus.setVersion(Version::string());
m_clientStatus.setCpuBrand(Cpu::brand());
m_clientStatus.setCpuAES(Cpu::hasAES());
m_clientStatus.setCpuSockets(static_cast<int>(Cpu::sockets()));
m_clientStatus.setCpuCores(static_cast<int>(Cpu::cores()));
m_clientStatus.setCpuThreads(static_cast<int>(Cpu::threads()));
m_clientStatus.setCpuX64(Cpu::isX64());
m_clientStatus.setCpuL2(static_cast<int>(Cpu::l2()));
m_clientStatus.setCpuL3(static_cast<int>(Cpu::l3()));
m_clientStatus.setCpuBrand(cpuInfo->brand());
m_clientStatus.setCpuAES(cpuInfo->hasAES());
m_clientStatus.setCpuSockets(static_cast<int>(cpuInfo->packages()));
m_clientStatus.setCpuCores(static_cast<int>(cpuInfo->cores()));
m_clientStatus.setCpuThreads(static_cast<int>(cpuInfo->threads()));
m_clientStatus.setCpuX64(cpuInfo->isX64());
m_clientStatus.setCpuL2(static_cast<int>(cpuInfo->L2()/1024));
m_clientStatus.setCpuL3(static_cast<int>(cpuInfo->L3()/1024));
m_clientStatus.setNodes(static_cast<int>(cpuInfo->nodes()));
# ifdef XMRIG_FEATURE_ASM
const Assembly assembly = Cpu::assembly(cpuInfo->assembly());
m_clientStatus.setAssembly(assembly.toString());
# else
m_clientStatus.setAssembly("none");
# endif
#ifdef TYPE_AMD_GPU
m_clientStatus.setCurrentThreads(static_cast<int>(config->threads().size()));
m_clientStatus.setCurrentAlgoName(config->algorithm().name());
#else
m_clientStatus.setCurrentThreads(static_cast<int>(config->threads()));
m_clientStatus.setCurrentAlgoName(config->algoName());
#endif
m_startTime = std::chrono::system_clock::now();
if (config->ccToken() != nullptr) {
m_authorization = std::string("Bearer ") + m_self->m_config->ccToken();
}
uv_thread_create(&m_thread, CCClient::onThreadStarted, this);
}
CCClient::~CCClient()
void xmrig::CCClient::stop()
{
uv_timer_stop(&m_timer);
m_self = nullptr;
}
LOG_DEBUG("CCClient::stop");
void CCClient::updateHashrate(const Hashrate* hashrate)
{
if (m_self) {
uv_mutex_lock(&m_mutex);
m_configPublishedOnStart = false;
m_self->m_clientStatus.setHashrateShort(hashrate->calc(Hashrate::ShortInterval));
m_self->m_clientStatus.setHashrateMedium(hashrate->calc(Hashrate::MediumInterval));
m_self->m_clientStatus.setHashrateLong(hashrate->calc(Hashrate::LargeInterval));
m_self->m_clientStatus.setHashrateHighest(hashrate->highest());
uv_mutex_unlock(&m_mutex);
if (m_timer) {
m_timer->stop();
}
}
void CCClient::updateNetworkState(const NetworkState& network)
void xmrig::CCClient::updateStatistics()
{
if (m_self) {
uv_mutex_lock(&m_mutex);
LOG_DEBUG("CCClient::updateStatistics");
m_self->m_clientStatus.setCurrentStatus(Workers::isEnabled() ? ClientStatus::RUNNING : ClientStatus::PAUSED);
m_self->m_clientStatus.setCurrentPool(network.pool);
m_self->m_clientStatus.setSharesGood(network.accepted);
m_self->m_clientStatus.setSharesTotal(network.accepted + network.rejected);
m_self->m_clientStatus.setHashesTotal(network.total);
m_self->m_clientStatus.setAvgTime(network.avgTime());
for (IClientStatusListener *listener : m_ClientStatislisteners) {
listener->onUpdateRequest(m_clientStatus);
}
#ifdef TYPE_AMD_GPU
m_self->m_clientStatus.setHashFactor(0);
m_self->m_clientStatus.setHugepagesEnabled(false);
m_self->m_clientStatus.setHugepages(false);
m_self->m_clientStatus.setTotalPages(0);
m_self->m_clientStatus.setTotalHugepages(0);
m_self->m_clientStatus.setCurrentPowVariantName(xmrig::Algorithm::getVariantName(network.powVariant));
#else
m_self->m_clientStatus.setHashFactor(Mem::hashFactor());
m_self->m_clientStatus.setHugepagesEnabled(Mem::isHugepagesEnabled());
m_self->m_clientStatus.setHugepages(Mem::isHugepagesAvailable());
m_self->m_clientStatus.setTotalPages(Mem::getTotalPages());
m_self->m_clientStatus.setTotalHugepages(Mem::getTotalHugepages());
m_self->m_clientStatus.setCurrentPowVariantName(getPowVariantName(network.powVariant));
m_self->m_clientStatus.setHashFactor(0);
m_self->m_clientStatus.setHugepagesEnabled(false);
m_self->m_clientStatus.setHugepages(false);
m_self->m_clientStatus.setTotalPages(0);
m_self->m_clientStatus.setTotalHugepages(0);
m_self->m_clientStatus.setCurrentPowVariantName(xmrig::Algorithm::getVariantName(network.powVariant));
#endif
uv_mutex_unlock(&m_mutex);
}
}
#ifdef TYPE_AMD_GPU
void CCClient::updateGpuInfo(const std::vector<GpuContext>& gpuContext)
{
LOG_DEBUG("CCClient::updateGpuInfo");
if (m_self) {
uv_mutex_lock(&m_mutex);
@ -189,67 +206,68 @@ void CCClient::updateGpuInfo(const std::vector<GpuContext>& gpuContext)
}
#endif
void CCClient::publishClientStatusReport()
void xmrig::CCClient::publishClientStatusReport()
{
std::string requestUrl = "/client/setClientStatus?clientId=" + m_self->m_clientStatus.getClientId();
std::string requestBuffer = m_self->m_clientStatus.toJsonString();
LOG_DEBUG("CCClient::publishClientStatusReport");
std::string requestUrl = "/client/setClientStatus?clientId=" + m_clientStatus.getClientId();
std::string requestBuffer = m_clientStatus.toJsonString();
auto res = performRequest(requestUrl, requestBuffer, "POST");
if (!res) {
LOG_ERR("[CC-Client] error: unable to performRequest POST -> http://%s:%d%s",
m_self->m_config->ccHost(), m_self->m_config->ccPort(), requestUrl.c_str());
m_base->config()->ccClient().host(), m_base->config()->ccClient().port(), requestUrl.c_str());
} else if (res->status != 200) {
LOG_ERR("[CC-Client] error: \"%d\" -> http://%s:%d%s", res->status,m_self->m_config->ccHost(),
m_self->m_config->ccPort(), requestUrl.c_str());
LOG_ERR("[CC-Client] error: \"%d\" -> http://%s:%d%s", res->status, m_base->config()->ccClient().host(),
m_base->config()->ccClient().port(), requestUrl.c_str());
} else {
ControlCommand controlCommand;
if (controlCommand.parseFromJsonString(res->body)) {
if (controlCommand.getCommand() == ControlCommand::START) {
if (!Workers::isEnabled()) {
LOG_WARN("[CC-Client] Command: START received -> resume");
}
LOG_DEBUG("[CC-Client] Command: START received -> resume");
} else if (controlCommand.getCommand() == ControlCommand::STOP) {
if (Workers::isEnabled()) {
LOG_WARN("[CC-Client] Command: STOP received -> pause");
}
LOG_DEBUG("[CC-Client] Command: STOP received -> pause");
} else if (controlCommand.getCommand() == ControlCommand::UPDATE_CONFIG) {
LOG_WARN("[CC-Client] Command: UPDATE_CONFIG received -> update config");
updateConfig();
fetchConfig();
} else if (controlCommand.getCommand() == ControlCommand::PUBLISH_CONFIG) {
LOG_WARN("[CC-Client] Command: PUBLISH_CONFIG received -> publish config");
publishConfig();
}else if (controlCommand.getCommand() == ControlCommand::RESTART) {
LOG_WARN("[CC-Client] Command: RESTART received -> trigger restart");
} else if (controlCommand.getCommand() == ControlCommand::SHUTDOWN) {
} else if (controlCommand.getCommand() == ControlCommand::SHUTDOWN) {
LOG_WARN("[CC-Client] Command: SHUTDOWN received -> quit");
} else if (controlCommand.getCommand() == ControlCommand::REBOOT) {
LOG_WARN("[CC-Client] Command: REBOOT received -> trigger reboot");
}
m_self->m_async->data = reinterpret_cast<void*>(controlCommand.getCommand());
uv_async_send(m_self->m_async);
for (ICommandListener *listener : m_Commandlisteners) {
listener->onCommandReceived(controlCommand);
}
} else {
LOG_ERR("[CC-Client] Unknown command received from CC Server.");
}
}
}
void CCClient::updateConfig()
void xmrig::CCClient::fetchConfig()
{
std::string requestUrl = "/client/getConfig?clientId=" + m_self->m_clientStatus.getClientId();
LOG_DEBUG("CCClient::fetchConfig");
std::string requestUrl = "/client/getConfig?clientId=" + m_clientStatus.getClientId();
std::string requestBuffer;
auto res = performRequest(requestUrl, requestBuffer, "GET");
if (!res) {
LOG_ERR("[CC-Client] error: unable to performRequest GET -> http://%s:%d%s",
m_self->m_config->ccHost(), m_self->m_config->ccPort(), requestUrl.c_str());
m_base->config()->ccClient().host(), m_base->config()->ccClient().port(), requestUrl.c_str());
} else if (res->status != 200) {
LOG_ERR("[CC-Client] error: \"%d\" -> http://%s:%d%s", res->status, m_self->m_config->ccHost(),
m_self->m_config->ccPort(), requestUrl.c_str());
LOG_ERR("[CC-Client] error: \"%d\" -> http://%s:%d%s", res->status, m_base->config()->ccClient().host(),
m_base->config()->ccClient().port(), requestUrl.c_str());
} else {
rapidjson::Document document;
if (!document.Parse(res->body.c_str()).HasParseError()) {
std::ofstream clientConfigFile(m_self->m_config->fileName());
std::ofstream clientConfigFile(m_base->config()->fileName());
if (clientConfigFile) {
rapidjson::StringBuffer buffer(0, 65536);
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
@ -259,9 +277,13 @@ void CCClient::updateConfig()
clientConfigFile << buffer.GetString();
clientConfigFile.close();
LOG_WARN("[CC-Client] Config updated. -> trigger restart");
if (!m_base->config()->isWatch()) {
dynamic_cast<IWatcherListener*>(m_base)->onFileChanged(m_base->config()->fileName());
}
LOG_WARN("[CC-Client] Config updated. -> reload");
} else {
LOG_ERR("[CC-Client] Not able to store client config to file %s.", m_self->m_config->fileName());
LOG_ERR("[CC-Client] Not able to store client config to file %s.", m_base->config()->fileName());
}
} else {
LOG_ERR("[CC-Client] Not able to store client config. received client config is broken!");
@ -269,12 +291,14 @@ void CCClient::updateConfig()
}
}
void CCClient::publishConfig()
void xmrig::CCClient::publishConfig()
{
std::string requestUrl = "/client/setClientConfig?clientId=" + m_self->m_clientStatus.getClientId();
LOG_DEBUG("CCClient::publishConfig");
std::string requestUrl = "/client/setClientConfig?clientId=" + m_clientStatus.getClientId();
std::stringstream data;
std::ifstream clientConfig(m_self->m_config->fileName());
std::ifstream clientConfig(m_base->config()->fileName());
if (clientConfig) {
data << clientConfig.rdbuf();
@ -294,32 +318,36 @@ void CCClient::publishConfig()
auto res = performRequest(requestUrl, buffer.GetString(), "POST");
if (!res) {
LOG_ERR("[CC-Client] error: unable to performRequest POST -> http://%s:%d%s",
m_self->m_config->ccHost(), m_self->m_config->ccPort(), requestUrl.c_str());
m_base->config()->ccClient().host(), m_base->config()->ccClient().port(), requestUrl.c_str());
} else if (res->status != 200) {
LOG_ERR("[CC-Client] error: \"%d\" -> http://%s:%d%s", res->status, m_self->m_config->ccHost(),
m_self->m_config->ccPort(), requestUrl.c_str());
LOG_ERR("[CC-Client] error: \"%d\" -> http://%s:%d%s", res->status, m_base->config()->ccClient().host(),
m_base->config()->ccClient().port(), requestUrl.c_str());
}
} else {
LOG_ERR("[CC-Client] Not able to send config. Client config %s is broken!", m_self->m_config->fileName());
LOG_ERR("[CC-Client] Not able to send config. Client config %s is broken!", m_base->config()->fileName());
}
} else {
LOG_ERR("[CC-Client] Not able to load client config %s. Please make sure it exists! Using embedded config.", m_self->m_config->fileName());
LOG_ERR("[CC-Client] Not able to load client config %s. Please make sure it exists! Using embedded config.", m_base->config()->fileName());
}
}
std::shared_ptr<httplib::Response> CCClient::performRequest(const std::string& requestUrl,
const std::string& requestBuffer,
const std::string& operation)
std::shared_ptr<httplib::Response> xmrig::CCClient::performRequest(const std::string& requestUrl,
const std::string& requestBuffer,
const std::string& operation)
{
LOG_DEBUG("CCClient::performRequest");
std::shared_ptr<httplib::Client> cli;
# ifndef XMRIG_NO_TLS
if (m_self->m_config->ccUseTls()) {
cli = std::make_shared<httplib::SSLClient>(m_self->m_config->ccHost(), m_self->m_config->ccPort(), 10);
# ifdef XMRIG_FEATURE_TLS
if (m_base->config()->ccClient().useTLS()) {
cli = std::make_shared<httplib::SSLClient>(m_base->config()->ccClient().host(),
m_base->config()->ccClient().port(), 10);
} else {
# endif
cli = std::make_shared<httplib::Client>(m_self->m_config->ccHost(), m_self->m_config->ccPort(), 10);
# ifndef XMRIG_NO_TLS
cli = std::make_shared<httplib::Client>(m_base->config()->ccClient().host(),
m_base->config()->ccClient().port(), 10);
# ifdef XMRIG_FEATURE_TLS
}
# endif
@ -327,13 +355,13 @@ std::shared_ptr<httplib::Response> CCClient::performRequest(const std::string& r
req.method = operation;
req.path = requestUrl;
req.set_header("Host", "");
req.set_header("Accept", "*/*");
req.set_header("Accept", "*//*");
req.set_header("User-Agent", Platform::userAgent());
req.set_header("Accept", "application/json");
req.set_header("Content-Type", "application/json");
if (!m_self->m_authorization.empty()) {
req.set_header("Authorization", m_self->m_authorization.c_str());
if (!m_authorization.empty()) {
req.set_header("Authorization", m_authorization.c_str());
}
if (!requestBuffer.empty()) {
@ -345,43 +373,49 @@ std::shared_ptr<httplib::Response> CCClient::performRequest(const std::string& r
return cli->send(req, *res) ? res : nullptr;
}
void CCClient::refreshUptime()
void xmrig::CCClient::updateUptime()
{
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
auto uptime = std::chrono::duration_cast<std::chrono::milliseconds>(now - m_self->m_startTime);
m_self->m_clientStatus.setUptime(static_cast<uint64_t>(uptime.count()));
LOG_DEBUG("CCClient::updateUptime");
m_clientStatus.setUptime(Chrono::currentMSecsSinceEpoch()-m_startTime);
}
void CCClient::refreshLog()
void xmrig::CCClient::updateLog()
{
m_self->m_clientStatus.setLog(RemoteLog::getRows());
LOG_DEBUG("CCClient::updateLog");
m_clientStatus.setLog(RemoteLog::getRows());
}
void CCClient::onThreadStarted(void* handle)
void xmrig::CCClient::onConfigChanged(Config *config, Config *previousConfig)
{
if (m_self) {
uv_loop_init(&m_self->m_client_loop);
LOG_DEBUG("CCClient::onConfigChanged");
if (config->ccClient() != previousConfig->ccClient()) {
stop();
uv_timer_init(&m_self->m_client_loop, &m_self->m_timer);
uv_timer_start(&m_self->m_timer, CCClient::onReport,
static_cast<uint64_t>(m_self->m_config->ccUpdateInterval() * 1000),
static_cast<uint64_t>(m_self->m_config->ccUpdateInterval() * 1000));
if (m_self->m_config->ccUploadConfigOnStartup()) {
m_self->publishConfig();
if (config->ccClient().enabled() && config->ccClient().host() && config->ccClient().port() > 0) {
start();
}
uv_run(&m_self->m_client_loop, UV_RUN_DEFAULT);
}
}
void CCClient::onReport(uv_timer_t* handle)
void xmrig::CCClient::onTimer(const xmrig::Timer *timer)
{
if (m_self) {
m_self->refreshUptime();
m_self->refreshLog();
m_self->publishClientStatusReport();
}
LOG_DEBUG("CCClient::onTimer");
std::thread(CCClient::publishThread, this).detach();
}
void xmrig::CCClient::publishThread(CCClient* handle)
{
LOG_DEBUG("CCClient::publishThread");
if (handle) {
if (!handle->m_configPublishedOnStart && handle->m_base->config()->ccClient().uploadConfigOnStartup()) {
handle->m_configPublishedOnStart = true;
handle->publishConfig();
}
handle->updateUptime();
handle->updateLog();
handle->updateStatistics();
handle->publishClientStatusReport();
}
}