Merge pull request #548 from SChernykh/dev

Sync changes with XMRig
This commit is contained in:
xmrig
2023-10-01 23:35:28 +07:00
committed by GitHub
16 changed files with 135 additions and 287 deletions

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2023 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2023 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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
@@ -123,6 +123,21 @@ void xmrig::Api::stop()
}
void xmrig::Api::tick()
{
# ifdef XMRIG_FEATURE_HTTP
if (m_httpd->isBound() || !m_base->config()->http().isEnabled()) {
return;
}
if (++m_ticks % 10 == 0) {
m_ticks = 0;
m_httpd->start();
}
# endif
}
void xmrig::Api::onConfigChanged(Config *config, Config *previousConfig)
{
if (config->apiId() != previousConfig->apiId()) {

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2023 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2023 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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,7 +21,6 @@
#include <vector>
#include <cstdint>
#include "base/kernel/interfaces/IBaseListener.h"
@@ -44,7 +43,7 @@ class Api : public IBaseListener
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(Api)
Api(Base *base);
explicit Api(Base *base);
~Api() override;
inline const char *id() const { return m_id; }
@@ -54,6 +53,7 @@ public:
void request(const HttpData &req);
void start();
void stop();
void tick();
protected:
void onConfigChanged(Config *config, Config *previousConfig) override;
@@ -65,14 +65,15 @@ private:
Base *m_base;
char m_id[32]{};
String m_workerId;
const uint64_t m_timestamp;
Httpd *m_httpd = nullptr;
Httpd *m_httpd = nullptr;
std::vector<IApiListener *> m_listeners;
String m_workerId;
uint8_t m_ticks = 0;
};
} // namespace xmrig
#endif /* XMRIG_API_H */
#endif // XMRIG_API_H

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2023 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2023 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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
@@ -22,11 +22,6 @@
#include "base/kernel/interfaces/IBaseListener.h"
#include "base/net/http/HttpListener.h"
#include "base/tools/Object.h"
#include <cstdint>
#include <memory>
namespace xmrig {
@@ -43,9 +38,11 @@ class Httpd : public IBaseListener, public IHttpListener
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(Httpd)
Httpd(Base *base);
explicit Httpd(Base *base);
~Httpd() override;
inline bool isBound() const { return m_server != nullptr; }
bool start();
void stop();
@@ -69,7 +66,7 @@ private:
};
} /* namespace xmrig */
} // namespace xmrig
#endif /* XMRIG_HTTPD_H */
#endif // XMRIG_HTTPD_H

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2023 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2023 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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
@@ -49,6 +49,12 @@ public:
static inline bool isUserActive(uint64_t ms) { return idleTime() < ms; }
static inline const String &userAgent() { return m_userAgent; }
# ifdef XMRIG_OS_WIN
static bool hasKeepalive();
# else
static constexpr bool hasKeepalive() { return true; }
# endif
static bool isOnBatteryPower();
static uint64_t idleTime();

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2023 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2023 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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
@@ -16,9 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base/kernel/Platform.h"
#include "backend/cpu/platform/HwlocCpuInfo.h"
#include "backend/cpu/Cpu.h"
@@ -29,20 +27,21 @@
#ifndef XMRIG_OS_APPLE
bool xmrig::Platform::setThreadAffinity(uint64_t cpu_id)
{
auto cpu = static_cast<HwlocCpuInfo *>(Cpu::info());
hwloc_obj_t pu = hwloc_get_pu_obj_by_os_index(cpu->topology(), static_cast<unsigned>(cpu_id));
auto topology = Cpu::info()->topology();
auto pu = hwloc_get_pu_obj_by_os_index(topology, static_cast<unsigned>(cpu_id));
if (pu == nullptr) {
return false;
}
if (hwloc_set_cpubind(cpu->topology(), pu->cpuset, HWLOC_CPUBIND_THREAD | HWLOC_CPUBIND_STRICT) >= 0) {
if (hwloc_set_cpubind(topology, pu->cpuset, HWLOC_CPUBIND_THREAD | HWLOC_CPUBIND_STRICT) >= 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
return true;
}
const bool result = (hwloc_set_cpubind(cpu->topology(), pu->cpuset, HWLOC_CPUBIND_THREAD) >= 0);
const bool result = (hwloc_set_cpubind(topology, pu->cpuset, HWLOC_CPUBIND_THREAD) >= 0);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
return result;
}
#endif

View File

@@ -1,6 +1,6 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2023 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2023 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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
@@ -16,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <winsock2.h>
#include <windows.h>
@@ -70,6 +69,12 @@ char *xmrig::Platform::createUserAgent()
}
bool xmrig::Platform::hasKeepalive()
{
return winOsVersion().dwMajorVersion >= 6;
}
#ifndef XMRIG_FEATURE_HWLOC
bool xmrig::Platform::setThreadAffinity(uint64_t cpu_id)
{

View File

@@ -142,7 +142,7 @@ void xmrig::BaseConfig::printVersions()
snprintf(buf, sizeof buf, "MSVC/%d", MSVC_VERSION);
# endif
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%s/%s") WHITE_BOLD(" %s"), "ABOUT", APP_NAME, APP_VERSION, buf);
Log::print(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%s/%s") WHITE_BOLD(" %s") WHITE_BOLD(" (built for %s") WHITE_BOLD(" %s,") WHITE_BOLD(" %s)"), "ABOUT", APP_NAME, APP_VERSION, buf, APP_OS, APP_ARCH, APP_BITS);
std::string libs;

View File

@@ -21,6 +21,7 @@
#define XMRIG_HTTPRESPONSE_H
#include <cstdint>
#include <map>
#include <string>

View File

@@ -1,7 +1,7 @@
/* XMRig
* Copyright (c) 2019 jtgrassie <https://github.com/jtgrassie>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2023 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2023 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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
@@ -42,13 +42,14 @@
#include "base/io/json/JsonRequest.h"
#include "base/io/log/Log.h"
#include "base/kernel/interfaces/IClientListener.h"
#include "base/kernel/Platform.h"
#include "base/net/dns/Dns.h"
#include "base/net/dns/DnsRecords.h"
#include "base/net/stratum/Socks5.h"
#include "base/net/tools/NetBuffer.h"
#include "base/tools/Chrono.h"
#include "base/tools/Cvt.h"
#include "base/tools/cryptonote/BlobReader.h"
#include "base/tools/Cvt.h"
#include "net/JobResult.h"
@@ -343,6 +344,9 @@ bool xmrig::Client::close()
setState(ClosingState);
if (uv_is_closing(reinterpret_cast<uv_handle_t*>(m_socket)) == 0) {
if (Platform::hasKeepalive()) {
uv_tcp_keepalive(m_socket, 0, 60);
}
uv_close(reinterpret_cast<uv_handle_t*>(m_socket), Client::onClose);
}
@@ -567,9 +571,9 @@ void xmrig::Client::connect(const sockaddr *addr)
uv_tcp_init(uv_default_loop(), m_socket);
uv_tcp_nodelay(m_socket, 1);
# ifndef WIN32
uv_tcp_keepalive(m_socket, 1, 60);
# endif
if (Platform::hasKeepalive()) {
uv_tcp_keepalive(m_socket, 1, 60);
}
uv_tcp_connect(req, m_socket, addr, onConnect);
}
@@ -585,7 +589,7 @@ void xmrig::Client::handshake()
if (isTLS()) {
m_expire = Chrono::steadyMSecs() + kResponseTimeout;
m_tls->handshake();
m_tls->handshake(m_pool.isSNI() ? m_pool.host().data() : nullptr);
}
else
# endif

View File

@@ -1,13 +1,13 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2019 Howard Chu <https://github.com/hyc>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright (c) 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright (c) 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright (c) 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright (c) 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright (c) 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright (c) 2019 Howard Chu <https://github.com/hyc>
* Copyright (c) 2018-2023 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2023 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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
@@ -23,7 +23,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <uv.h>
@@ -34,6 +33,7 @@
#include "base/io/json/JsonRequest.h"
#include "base/io/log/Log.h"
#include "base/kernel/interfaces/IClientListener.h"
#include "base/kernel/Platform.h"
#include "base/net/dns/Dns.h"
#include "base/net/dns/DnsRecords.h"
#include "base/net/http/Fetch.h"
@@ -42,9 +42,9 @@
#include "base/net/stratum/SubmitResult.h"
#include "base/net/tools/NetBuffer.h"
#include "base/tools/bswap_64.h"
#include "base/tools/cryptonote/Signatures.h"
#include "base/tools/Cvt.h"
#include "base/tools/Timer.h"
#include "base/tools/cryptonote/Signatures.h"
#include "net/JobResult.h"
@@ -358,9 +358,9 @@ void xmrig::DaemonClient::onResolved(const DnsRecords &records, int status, cons
uv_tcp_init(uv_default_loop(), s);
uv_tcp_nodelay(s, 1);
# ifndef WIN32
uv_tcp_keepalive(s, 1, 60);
# endif
if (Platform::hasKeepalive()) {
uv_tcp_keepalive(s, 1, 60);
}
if (m_pool.zmq_port() > 0) {
delete m_ZMQSocket;
@@ -589,6 +589,9 @@ void xmrig::DaemonClient::retry()
}
if ((m_ZMQConnectionState != ZMQ_NOT_CONNECTED) && (m_ZMQConnectionState != ZMQ_DISCONNECTING)) {
if (Platform::hasKeepalive()) {
uv_tcp_keepalive(m_ZMQSocket, 0, 60);
}
uv_close(reinterpret_cast<uv_handle_t*>(m_ZMQSocket), onZMQClose);
}
@@ -916,6 +919,9 @@ bool xmrig::DaemonClient::ZMQClose(bool shutdown)
m_ZMQConnectionState = ZMQ_DISCONNECTING;
if (uv_is_closing(reinterpret_cast<uv_handle_t*>(m_ZMQSocket)) == 0) {
if (Platform::hasKeepalive()) {
uv_tcp_keepalive(m_ZMQSocket, 0, 60);
}
uv_close(reinterpret_cast<uv_handle_t*>(m_ZMQSocket), shutdown ? onZMQShutdown : onZMQClose);
if (!shutdown) {
retry();

View File

@@ -77,6 +77,7 @@ const char *Pool::kSelfSelect = "self-select";
const char *Pool::kSOCKS5 = "socks5";
const char *Pool::kSubmitToOrigin = "submit-to-origin";
const char *Pool::kTls = "tls";
const char *Pool::kSni = "sni";
const char *Pool::kUrl = "url";
const char *Pool::kUser = "user";
const char *Pool::kSpendSecretKey = "spend-secret-key";
@@ -137,6 +138,7 @@ xmrig::Pool::Pool(const rapidjson::Value &object) :
m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true));
m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash) || m_url.host().contains(kNicehashHost));
m_flags.set(FLAG_TLS, Json::getBool(object, kTls) || m_url.isTLS());
m_flags.set(FLAG_SNI, Json::getBool(object, kSni));
setKeepAlive(Json::getValue(object, kKeepalive));
@@ -299,6 +301,7 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
obj.AddMember(StringRef(kEnabled), m_flags.test(FLAG_ENABLED), allocator);
obj.AddMember(StringRef(kTls), isTLS(), allocator);
obj.AddMember(StringRef(kSni), isSNI(), allocator);
obj.AddMember(StringRef(kFingerprint), m_fingerprint.toJSON(), allocator);
obj.AddMember(StringRef(kDaemon), m_mode == MODE_DAEMON, allocator);
obj.AddMember(StringRef(kSOCKS5), m_proxy.toJSON(doc), allocator);

View File

@@ -70,6 +70,7 @@ public:
static const char *kSOCKS5;
static const char *kSubmitToOrigin;
static const char *kTls;
static const char* kSni;
static const char *kUrl;
static const char *kUser;
static const char* kSpendSecretKey;
@@ -95,6 +96,7 @@ public:
inline bool isNicehash() const { return m_flags.test(FLAG_NICEHASH); }
inline bool isTLS() const { return m_flags.test(FLAG_TLS) || m_url.isTLS(); }
inline bool isSNI() const { return m_flags.test(FLAG_SNI); }
inline bool isValid() const { return m_url.isValid(); }
inline const Algorithm &algorithm() const { return m_algorithm; }
inline const Coin &coin() const { return m_coin; }
@@ -138,6 +140,7 @@ private:
FLAG_ENABLED,
FLAG_NICEHASH,
FLAG_TLS,
FLAG_SNI,
FLAG_MAX
};

View File

@@ -60,7 +60,7 @@ xmrig::Client::Tls::~Tls()
}
bool xmrig::Client::Tls::handshake()
bool xmrig::Client::Tls::handshake(const char* servername)
{
m_ssl = SSL_new(m_ctx);
assert(m_ssl != nullptr);
@@ -69,6 +69,10 @@ bool xmrig::Client::Tls::handshake()
return false;
}
if (servername) {
SSL_set_tlsext_host_name(m_ssl, servername);
}
SSL_set_connect_state(m_ssl);
SSL_set_bio(m_ssl, m_read, m_write);
SSL_do_handshake(m_ssl);

View File

@@ -42,7 +42,7 @@ public:
Tls(Client *client);
~Tls();
bool handshake();
bool handshake(const char* servername);
bool send(const char *data, size_t size);
const char *fingerprint() const;
const char *version() const;

View File

@@ -1,231 +0,0 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base/tools/Buffer.h"
#include <random>
namespace xmrig {
static std::random_device randomDevice;
static std::mt19937 randomEngine(randomDevice());
} // namespace xmrig
static inline uint8_t hf_hex2bin(uint8_t c, bool &err)
{
if (c >= '0' && c <= '9') {
return c - '0';
}
if (c >= 'a' && c <= 'f') {
return c - 'a' + 0xA;
}
if (c >= 'A' && c <= 'F') {
return c - 'A' + 0xA;
}
err = true;
return 0;
}
static inline uint8_t hf_bin2hex(uint8_t c)
{
if (c <= 0x9) {
return '0' + c;
}
return 'a' - 0xA + c;
}
xmrig::Buffer::Buffer(Buffer &&other) noexcept :
m_data(other.m_data),
m_size(other.m_size)
{
other.m_data = nullptr;
other.m_size = 0;
}
xmrig::Buffer::Buffer(const Buffer &other)
{
copy(other.data(), other.size());
}
xmrig::Buffer::Buffer(const char *data, size_t size)
{
copy(data, size);
}
xmrig::Buffer::Buffer(size_t size) :
m_size(size)
{
if (size > 0) {
m_data = new char[size]();
}
}
xmrig::Buffer::~Buffer()
{
delete [] m_data;
}
void xmrig::Buffer::from(const char *data, size_t size)
{
if (m_size > 0) {
if (m_size == size) {
memcpy(m_data, data, m_size);
return;
}
delete [] m_data;
}
copy(data, size);
}
xmrig::Buffer xmrig::Buffer::allocUnsafe(size_t size)
{
if (size == 0) {
return {};
}
Buffer buf;
buf.m_size = size;
buf.m_data = new char[size];
return buf;
}
xmrig::Buffer xmrig::Buffer::randomBytes(const size_t size)
{
Buffer buf(size);
std::uniform_int_distribution<> dis(0, 255);
for (size_t i = 0; i < size; ++i) {
buf.m_data[i] = static_cast<char>(dis(randomEngine));
}
return buf;
}
bool xmrig::Buffer::fromHex(const uint8_t *in, size_t size, uint8_t *out)
{
bool error = false;
for (size_t i = 0; i < size; i += 2) {
out[i / 2] = static_cast<uint8_t>((hf_hex2bin(in[i], error) << 4) | hf_hex2bin(in[i + 1], error));
if (error) {
return false;
}
}
return true;
}
xmrig::Buffer xmrig::Buffer::fromHex(const char *data, size_t size)
{
if (data == nullptr || size % 2 != 0) {
return {};
}
Buffer buf(size / 2);
if (!fromHex(data, size, buf.data())) {
return {};
}
return buf;
}
void xmrig::Buffer::toHex(const uint8_t *in, size_t size, uint8_t *out)
{
for (size_t i = 0; i < size; i++) {
out[i * 2] = hf_bin2hex((in[i] & 0xF0) >> 4);
out[i * 2 + 1] = hf_bin2hex(in[i] & 0x0F);
}
}
xmrig::String xmrig::Buffer::toHex() const
{
if (m_size == 0) {
return String();
}
char *buf = new char[m_size * 2 + 1];
buf[m_size * 2] = '\0';
toHex(m_data, m_size, buf);
return String(buf);
}
void xmrig::Buffer::copy(const char *data, size_t size)
{
if (size == 0) {
m_data = nullptr;
m_size = 0;
return;
}
m_data = new char[size];
m_size = size;
memcpy(m_data, data, m_size);
}
void xmrig::Buffer::move(Buffer &&other)
{
if (m_size > 0) {
delete [] m_data;
}
m_data = other.m_data;
m_size = other.m_size;
other.m_data = nullptr;
other.m_size = 0;
}

View File

@@ -52,4 +52,39 @@
# endif
#endif
#ifdef XMRIG_OS_WIN
# define APP_OS "Windows"
#elif defined XMRIG_OS_IOS
# define APP_OS "iOS"
#elif defined XMRIG_OS_MACOS
# define APP_OS "macOS"
#elif defined XMRIG_OS_ANDROID
# define APP_OS "Android"
#elif defined XMRIG_OS_LINUX
# define APP_OS "Linux"
#elif defined XMRIG_OS_FREEBSD
# define APP_OS "FreeBSD"
#else
# define APP_OS "Unknown OS"
#endif
#define STR(X) #X
#define STR2(X) STR(X)
#ifdef XMRIG_ARM
# define APP_ARCH "ARMv" STR2(XMRIG_ARM)
#else
# if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) || defined(_M_AMD64)
# define APP_ARCH "x86-64"
# else
# define APP_ARCH "x86"
# endif
#endif
#ifdef XMRIG_64_BIT
# define APP_BITS "64 bit"
#else
# define APP_BITS "32 bit"
#endif
#endif // XMRIG_VERSION_H