Merge branch 'dev'

This commit is contained in:
XMRig 2021-08-09 16:08:20 +07:00
commit 43e98c509a
No known key found for this signature in database
GPG key ID: 446A53638BE94409
23 changed files with 676 additions and 90 deletions

View file

@ -1,3 +1,9 @@
# v6.14.0
- [#2484](https://github.com/xmrig/xmrig/pull/2484) Added ZeroMQ support for solo mining.
- [#2476](https://github.com/xmrig/xmrig/issues/2476) Fixed crash in DMI memory reader.
- [#2492](https://github.com/xmrig/xmrig/issues/2492) Added missing `--huge-pages-jit` command line option.
- [#2512](https://github.com/xmrig/xmrig/pull/2512) Added show the number of transactions in pool job.
# v6.13.1
- [#2468](https://github.com/xmrig/xmrig/pull/2468) Fixed regression in previous version: don't send miner signature during regular mining.

View file

@ -70,6 +70,7 @@ set(HEADERS_BASE
src/base/net/tools/Storage.h
src/base/tools/Arguments.h
src/base/tools/Baton.h
src/base/tools/bswap_64.h
src/base/tools/Buffer.h
src/base/tools/Chrono.h
src/base/tools/Cvt.h

View file

@ -242,13 +242,14 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
return set(doc, BaseConfig::kTls, TlsConfig::kGen, arg);
# endif
case IConfig::RetriesKey: /* --retries */
case IConfig::RetryPauseKey: /* --retry-pause */
case IConfig::PrintTimeKey: /* --print-time */
case IConfig::HttpPort: /* --http-port */
case IConfig::DonateLevelKey: /* --donate-level */
case IConfig::DaemonPollKey: /* --daemon-poll-interval */
case IConfig::DnsTtlKey: /* --dns-ttl */
case IConfig::RetriesKey: /* --retries */
case IConfig::RetryPauseKey: /* --retry-pause */
case IConfig::PrintTimeKey: /* --print-time */
case IConfig::HttpPort: /* --http-port */
case IConfig::DonateLevelKey: /* --donate-level */
case IConfig::DaemonPollKey: /* --daemon-poll-interval */
case IConfig::DnsTtlKey: /* --dns-ttl */
case IConfig::DaemonZMQPortKey: /* --daemon-zmq-port */
return transformUint64(doc, key, static_cast<uint64_t>(strtol(arg, nullptr, 10)));
case IConfig::BackgroundKey: /* --background */
@ -359,6 +360,9 @@ void xmrig::BaseTransform::transformUint64(rapidjson::Document &doc, int key, ui
# ifdef XMRIG_FEATURE_HTTP
case IConfig::DaemonPollKey: /* --daemon-poll-interval */
return add(doc, Pools::kPools, Pool::kDaemonPollInterval, arg);
case IConfig::DaemonZMQPortKey: /* --daemon-zmq-port */
return add(doc, Pools::kPools, Pool::kDaemonZMQPort, arg);
# endif
default:

View file

@ -85,6 +85,8 @@ public:
DnsIPv6Key = 1053,
DnsTtlKey = 1054,
SpendSecretKey = 1055,
DaemonZMQPortKey = 1056,
HugePagesJitKey = 1057,
// xmrig common
CPUPriorityKey = 1021,

View file

@ -6,8 +6,8 @@
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2019 jtgrassie <https://github.com/jtgrassie>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 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
@ -225,6 +225,10 @@ int64_t xmrig::Client::submit(const JobResult &result)
if (result.minerSignature()) {
params.AddMember("sig", StringRef(signature), allocator);
}
# else
if (result.sig) {
params.AddMember("sig", StringRef(result.sig), allocator);
}
# endif
if (has<EXT_ALGO>() && result.algorithm.isValid()) {
@ -440,12 +444,7 @@ bool xmrig::Client::parseJob(const rapidjson::Value &params, int *code)
return false;
}
# ifndef XMRIG_PROXY_PROJECT
uint8_t signatureKeyBuf[32 * 2];
if (Cvt::fromHex(signatureKeyBuf, sizeof(signatureKeyBuf), Json::getValue(params, "sig_key"))) {
job.setEphemeralKeys(signatureKeyBuf, signatureKeyBuf + 32);
}
# endif
job.setSigKey(Json::getString(params, "sig_key"));
m_job.setClientId(m_rpcId);

View file

@ -6,8 +6,8 @@
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2019 jtgrassie <https://github.com/jtgrassie>
* Copyright 2018-2020 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2020 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 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

View file

@ -31,10 +31,14 @@
#include "base/io/json/JsonRequest.h"
#include "base/io/log/Log.h"
#include "base/kernel/interfaces/IClientListener.h"
#include "base/net/dns/Dns.h"
#include "base/net/dns/DnsRecords.h"
#include "base/net/http/Fetch.h"
#include "base/net/http/HttpData.h"
#include "base/net/http/HttpListener.h"
#include "base/net/stratum/SubmitResult.h"
#include "base/net/tools/NetBuffer.h"
#include "base/tools/bswap_64.h"
#include "base/tools/Cvt.h"
#include "base/tools/Timer.h"
#include "base/tools/cryptonote/Signatures.h"
@ -48,7 +52,11 @@
namespace xmrig {
static const char *kBlocktemplateBlob = "blocktemplate_blob";
Storage<DaemonClient> DaemonClient::m_storage;
static const char* kBlocktemplateBlob = "blocktemplate_blob";
static const char *kGetHeight = "/getheight";
static const char *kGetInfo = "/getinfo";
static const char *kHash = "hash";
@ -57,6 +65,12 @@ static const char *kJsonRPC = "/json_rpc";
static constexpr size_t kBlobReserveSize = 8;
static const char kZMQGreeting[64] = { -1, 0, 0, 0, 0, 0, 0, 0, 0, 127, 3, 0, 'N', 'U', 'L', 'L' };
static constexpr size_t kZMQGreetingSize1 = 11;
static const char kZMQHandshake[] = "\4\x19\5READY\xbSocket-Type\0\0\0\3SUB";
static const char kZMQSubscribe[] = "\0\x18\1json-minimal-chain_main";
}
@ -65,12 +79,25 @@ xmrig::DaemonClient::DaemonClient(int id, IClientListener *listener) :
{
m_httpListener = std::make_shared<HttpListener>(this);
m_timer = new Timer(this);
m_key = m_storage.add(this);
}
xmrig::DaemonClient::~DaemonClient()
{
delete m_timer;
delete m_ZMQSocket;
}
void xmrig::DaemonClient::deleteLater()
{
if (m_pool.zmq_port() >= 0) {
ZMQClose(true);
}
else {
delete this;
}
}
@ -96,7 +123,7 @@ bool xmrig::DaemonClient::isTLS() const
int64_t xmrig::DaemonClient::submit(const JobResult &result)
{
if (result.jobId != (m_blocktemplateStr.data() + m_blocktemplateStr.size() - 32)) {
if (result.jobId != m_currentJobId) {
return -1;
}
@ -114,6 +141,10 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result)
memcpy(data + m_blocktemplate.eph_public_key_index * 2, result.sig_data + 32 * 2, 32 * 2);
}
if (result.extra_nonce >= 0) {
Cvt::toHex(data + m_blocktemplate.tx_extra_nonce_index * 2, 8, reinterpret_cast<const uint8_t*>(&result.extra_nonce), 4);
}
# else
Cvt::toHex(data + m_job.nonceOffset() * 2, 8, reinterpret_cast<const uint8_t*>(&result.nonce), 4);
@ -155,7 +186,13 @@ void xmrig::DaemonClient::connect()
}
setState(ConnectingState);
getBlockTemplate();
if (m_pool.zmq_port() >= 0) {
m_dns = Dns::resolve(m_pool.host(), this);
}
else {
getBlockTemplate();
}
}
@ -234,7 +271,7 @@ void xmrig::DaemonClient::onHttpData(const HttpData &data)
void xmrig::DaemonClient::onTimer(const Timer *)
{
if (m_state == ConnectingState) {
getBlockTemplate();
connect();
}
else if (m_state == ConnectedState) {
if (m_apiVersion == API_DERO) {
@ -247,6 +284,43 @@ void xmrig::DaemonClient::onTimer(const Timer *)
}
void xmrig::DaemonClient::onResolved(const DnsRecords& records, int status, const char* error)
{
m_dns.reset();
if (status < 0 && records.isEmpty()) {
if (!isQuiet()) {
LOG_ERR("%s " RED("DNS error: ") RED_BOLD("\"%s\""), tag(), error);
}
retry();
return;
}
if (m_ZMQSocket) {
delete m_ZMQSocket;
}
const auto& record = records.get();
m_ip = record.ip();
uv_connect_t* req = new uv_connect_t;
req->data = m_storage.ptr(m_key);
m_ZMQSocket = new uv_tcp_t;
m_ZMQSocket->data = m_storage.ptr(m_key);
uv_tcp_init(uv_default_loop(), m_ZMQSocket);
uv_tcp_nodelay(m_ZMQSocket, 1);
# ifndef WIN32
uv_tcp_keepalive(m_ZMQSocket, 1, 60);
# endif
uv_tcp_connect(req, m_ZMQSocket, record.addr(m_pool.zmq_port()), onZMQConnect);
}
bool xmrig::DaemonClient::isOutdated(uint64_t height, const char *hash) const
{
return m_job.height() != height || m_prevHash != hash;
@ -277,6 +351,19 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value &params, int *code)
return false;
}
# ifdef XMRIG_PROXY_PROJECT
const size_t k = m_blocktemplate.miner_tx_prefix_begin_index;
job.setMinerTx(
m_blocktemplate.raw_blob.data() + k,
m_blocktemplate.raw_blob.data() + m_blocktemplate.miner_tx_prefix_end_index,
m_blocktemplate.eph_public_key_index - k,
m_blocktemplate.tx_pubkey_index - k,
m_blocktemplate.tx_extra_nonce_index - k,
m_blocktemplate.tx_extra_nonce_size,
m_blocktemplate.miner_tx_merkle_tree_branch
);
# endif
m_blockhashingblob = Json::getString(params, "blockhashing_blob");
if (m_blocktemplate.has_miner_signature) {
@ -308,13 +395,6 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value &params, int *code)
# ifdef XMRIG_PROXY_PROJECT
job.setSpendSecretKey(secret_spendkey);
job.setMinerTx(
m_blocktemplate.raw_blob.data() + m_blocktemplate.miner_tx_prefix_begin_index,
m_blocktemplate.raw_blob.data() + m_blocktemplate.miner_tx_prefix_end_index,
m_blocktemplate.eph_public_key_index - m_blocktemplate.miner_tx_prefix_begin_index,
m_blocktemplate.tx_pubkey_index - m_blocktemplate.miner_tx_prefix_begin_index,
m_blocktemplate.miner_tx_merkle_tree_branch
);
# else
uint8_t secret_viewkey[32];
derive_view_secret_key(secret_spendkey, secret_viewkey);
@ -377,7 +457,8 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value &params, int *code)
job.setHeight(Json::getUint64(params, kHeight));
job.setDiff(Json::getUint64(params, "difficulty"));
job.setId(blocktemplate.data() + blocktemplate.size() - 32);
m_currentJobId = Cvt::toHex(Cvt::randomBytes(4));
job.setId(m_currentJobId);
m_job = std::move(job);
m_blocktemplateStr = std::move(blocktemplate);
@ -441,7 +522,9 @@ bool xmrig::DaemonClient::parseResponse(int64_t id, const rapidjson::Value &resu
}
if (handleSubmitResponse(id, error_msg)) {
getBlockTemplate();
if (error_msg || (m_pool.zmq_port() < 0)) {
getBlockTemplate();
}
return true;
}
@ -493,6 +576,10 @@ void xmrig::DaemonClient::retry()
setState(ConnectingState);
}
if ((m_ZMQConnectionState != ZMQ_NOT_CONNECTED) && (m_ZMQConnectionState != ZMQ_DISCONNECTING)) {
uv_close(reinterpret_cast<uv_handle_t*>(m_ZMQSocket), onZMQClose);
}
m_timer->stop();
m_timer->start(m_retryPause, 0);
}
@ -520,8 +607,10 @@ void xmrig::DaemonClient::setState(SocketState state)
m_failures = 0;
m_listener->onLoginSuccess(this);
const uint64_t interval = std::max<uint64_t>(20, m_pool.pollInterval());
m_timer->start(interval, interval);
if (m_pool.zmq_port() < 0) {
const uint64_t interval = std::max<uint64_t>(20, m_pool.pollInterval());
m_timer->start(interval, interval);
}
}
break;
@ -534,3 +623,282 @@ void xmrig::DaemonClient::setState(SocketState state)
break;
}
}
void xmrig::DaemonClient::onZMQConnect(uv_connect_t* req, int status)
{
DaemonClient* client = getClient(req->data);
delete req;
if (!client) {
return;
}
if (status < 0) {
LOG_ERR("%s " RED("ZMQ connect error: ") RED_BOLD("\"%s\""), client->tag(), uv_strerror(status));
client->retry();
return;
}
client->ZMQConnected();
}
void xmrig::DaemonClient::onZMQRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
{
DaemonClient* client = getClient(stream->data);
if (client) {
client->ZMQRead(nread, buf);
}
NetBuffer::release(buf);
}
void xmrig::DaemonClient::onZMQClose(uv_handle_t* handle)
{
DaemonClient* client = getClient(handle->data);
if (client) {
# ifdef APP_DEBUG
LOG_DEBUG(CYAN("tcp-zmq://%s:%u") BLACK_BOLD(" disconnected"), client->m_pool.host().data(), client->m_pool.zmq_port());
# endif
client->m_ZMQConnectionState = ZMQ_NOT_CONNECTED;
}
}
void xmrig::DaemonClient::onZMQShutdown(uv_handle_t* handle)
{
DaemonClient* client = getClient(handle->data);
if (client) {
# ifdef APP_DEBUG
LOG_DEBUG(CYAN("tcp-zmq://%s:%u") BLACK_BOLD(" shutdown"), client->m_pool.host().data(), client->m_pool.zmq_port());
# endif
client->m_ZMQConnectionState = ZMQ_NOT_CONNECTED;
m_storage.remove(client->m_key);
}
}
void xmrig::DaemonClient::ZMQConnected()
{
# ifdef APP_DEBUG
LOG_DEBUG(CYAN("tcp-zmq://%s:%u") BLACK_BOLD(" connected"), m_pool.host().data(), m_pool.zmq_port());
# endif
m_ZMQConnectionState = ZMQ_GREETING_1;
m_ZMQSendBuf.reserve(256);
m_ZMQRecvBuf.reserve(256);
if (ZMQWrite(kZMQGreeting, kZMQGreetingSize1)) {
uv_read_start(reinterpret_cast<uv_stream_t*>(m_ZMQSocket), NetBuffer::onAlloc, onZMQRead);
}
}
bool xmrig::DaemonClient::ZMQWrite(const char* data, size_t size)
{
m_ZMQSendBuf.assign(data, data + size);
uv_buf_t buf;
buf.base = m_ZMQSendBuf.data();
buf.len = static_cast<uint32_t>(m_ZMQSendBuf.size());
const int rc = uv_try_write(reinterpret_cast<uv_stream_t*>(m_ZMQSocket), &buf, 1);
if (static_cast<size_t>(rc) == buf.len) {
return true;
}
LOG_ERR("%s " RED("ZMQ write failed, rc = %d"), tag(), rc);
ZMQClose();
return false;
}
void xmrig::DaemonClient::ZMQRead(ssize_t nread, const uv_buf_t* buf)
{
if (nread <= 0) {
LOG_ERR("%s " RED("ZMQ read failed, nread = %" PRId64), tag(), nread);
ZMQClose();
return;
}
m_ZMQRecvBuf.insert(m_ZMQRecvBuf.end(), buf->base, buf->base + nread);
do {
switch (m_ZMQConnectionState) {
case ZMQ_GREETING_1:
if (m_ZMQRecvBuf.size() >= kZMQGreetingSize1) {
if ((m_ZMQRecvBuf[0] == -1) && (m_ZMQRecvBuf[9] == 127) && (m_ZMQRecvBuf[10] == 3)) {
ZMQWrite(kZMQGreeting + kZMQGreetingSize1, sizeof(kZMQGreeting) - kZMQGreetingSize1);
m_ZMQConnectionState = ZMQ_GREETING_2;
break;
}
else {
LOG_ERR("%s " RED("ZMQ handshake failed: invalid greeting format"), tag());
ZMQClose();
}
}
return;
case ZMQ_GREETING_2:
if (m_ZMQRecvBuf.size() >= sizeof(kZMQGreeting)) {
if (memcmp(m_ZMQRecvBuf.data() + 12, kZMQGreeting + 12, 20) == 0) {
m_ZMQConnectionState = ZMQ_HANDSHAKE;
m_ZMQRecvBuf.erase(m_ZMQRecvBuf.begin(), m_ZMQRecvBuf.begin() + sizeof(kZMQGreeting));
ZMQWrite(kZMQHandshake, sizeof(kZMQHandshake) - 1);
break;
}
else {
LOG_ERR("%s " RED("ZMQ handshake failed: invalid greeting format 2"), tag());
ZMQClose();
}
}
return;
case ZMQ_HANDSHAKE:
if (m_ZMQRecvBuf.size() >= 2) {
if (m_ZMQRecvBuf[0] != 4) {
LOG_ERR("%s " RED("ZMQ handshake failed: invalid handshake format"), tag());
ZMQClose();
return;
}
const size_t size = static_cast<unsigned char>(m_ZMQRecvBuf[1]);
if (size < 18) {
LOG_ERR("%s " RED("ZMQ handshake failed: invalid handshake size"), tag());
ZMQClose();
return;
}
if (m_ZMQRecvBuf.size() < size + 2) {
return;
}
if (memcmp(m_ZMQRecvBuf.data() + 2, kZMQHandshake + 2, 18) != 0) {
LOG_ERR("%s " RED("ZMQ handshake failed: invalid handshake data"), tag());
ZMQClose();
return;
}
ZMQWrite(kZMQSubscribe, sizeof(kZMQSubscribe) - 1);
m_ZMQConnectionState = ZMQ_CONNECTED;
m_ZMQRecvBuf.erase(m_ZMQRecvBuf.begin(), m_ZMQRecvBuf.begin() + size + 2);
getBlockTemplate();
break;
}
return;
case ZMQ_CONNECTED:
ZMQParse();
return;
default:
return;
}
} while (true);
}
void xmrig::DaemonClient::ZMQParse()
{
# ifdef APP_DEBUG
std::vector<char> msg;
# endif
size_t msg_size = 0;
char* data = m_ZMQRecvBuf.data();
size_t avail = m_ZMQRecvBuf.size();
bool more;
do {
if (avail < 1) {
return;
}
more = (data[0] & 1) != 0;
const bool long_size = (data[0] & 2) != 0;
const bool command = (data[0] & 4) != 0;
++data;
--avail;
uint64_t size = 0;
if (long_size)
{
if (avail < sizeof(uint64_t)) {
return;
}
size = bswap_64(*((uint64_t*)data));
data += sizeof(uint64_t);
avail -= sizeof(uint64_t);
}
else
{
if (avail < sizeof(uint8_t)) {
return;
}
size = static_cast<uint8_t>(*data);
++data;
--avail;
}
if (size > 1024U - msg_size)
{
LOG_ERR("%s " RED("ZMQ message is too large, size = %" PRIu64 " bytes"), tag(), size);
ZMQClose();
return;
}
if (avail < size) {
return;
}
if (!command) {
# ifdef APP_DEBUG
msg.insert(msg.end(), data, data + size);
# endif
msg_size += size;
}
data += size;
avail -= size;
} while (more);
m_ZMQRecvBuf.erase(m_ZMQRecvBuf.begin(), m_ZMQRecvBuf.begin() + (data - m_ZMQRecvBuf.data()));
# ifdef APP_DEBUG
LOG_DEBUG(CYAN("tcp-zmq://%s:%u") BLACK_BOLD(" read ") CYAN_BOLD("%zu") BLACK_BOLD(" bytes") " %s", m_pool.host().data(), m_pool.zmq_port(), msg.size(), msg.data());
# endif
getBlockTemplate();
}
bool xmrig::DaemonClient::ZMQClose(bool shutdown)
{
if ((m_ZMQConnectionState == ZMQ_NOT_CONNECTED) || (m_ZMQConnectionState == ZMQ_DISCONNECTING)) {
if (shutdown) {
m_storage.remove(m_key);
}
return false;
}
m_ZMQConnectionState = ZMQ_DISCONNECTING;
if (uv_is_closing(reinterpret_cast<uv_handle_t*>(m_ZMQSocket)) == 0) {
uv_close(reinterpret_cast<uv_handle_t*>(m_ZMQSocket), shutdown ? onZMQShutdown : onZMQClose);
if (!shutdown) {
retry();
}
return true;
}
return false;
}

View file

@ -27,11 +27,16 @@
#define XMRIG_DAEMONCLIENT_H
#include <uv.h>
#include "base/kernel/interfaces/IDnsListener.h"
#include "base/kernel/interfaces/IHttpListener.h"
#include "base/kernel/interfaces/ITimerListener.h"
#include "base/net/stratum/BaseClient.h"
#include "base/tools/Object.h"
#include "base/tools/cryptonote/BlockTemplate.h"
#include "base/net/tools/Storage.h"
#include <memory>
@ -40,7 +45,10 @@
namespace xmrig {
class DaemonClient : public BaseClient, public ITimerListener, public IHttpListener
class DnsRequest;
class DaemonClient : public BaseClient, public IDnsListener, public ITimerListener, public IHttpListener
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(DaemonClient)
@ -57,6 +65,7 @@ protected:
void onHttpData(const HttpData &data) override;
void onTimer(const Timer *timer) override;
void onResolved(const DnsRecords& records, int status, const char* error) override;
inline bool hasExtension(Extension) const noexcept override { return false; }
inline const char *mode() const override { return "daemon"; }
@ -64,7 +73,7 @@ protected:
inline const char *tlsVersion() const override { return m_tlsVersion; }
inline int64_t send(const rapidjson::Value &, Callback) override { return -1; }
inline int64_t send(const rapidjson::Value &) override { return -1; }
inline void deleteLater() override { delete this; }
void deleteLater() override;
inline void tick(uint64_t) override {}
private:
@ -84,6 +93,7 @@ private:
} m_apiVersion = API_MONERO;
std::shared_ptr<IHttpListener> m_httpListener;
String m_currentJobId;
String m_blocktemplateStr;
String m_blockhashingblob;
String m_prevHash;
@ -94,6 +104,38 @@ private:
String m_blocktemplateRequestHash;
BlockTemplate m_blocktemplate;
private:
static inline DaemonClient* getClient(void* data) { return m_storage.get(data); }
uintptr_t m_key = 0;
static Storage<DaemonClient> m_storage;
static void onZMQConnect(uv_connect_t* req, int status);
static void onZMQRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
static void onZMQClose(uv_handle_t* handle);
static void onZMQShutdown(uv_handle_t* handle);
void ZMQConnected();
bool ZMQWrite(const char* data, size_t size);
void ZMQRead(ssize_t nread, const uv_buf_t* buf);
void ZMQParse();
bool ZMQClose(bool shutdown = false);
std::shared_ptr<DnsRequest> m_dns;
uv_tcp_t* m_ZMQSocket = nullptr;
enum {
ZMQ_NOT_CONNECTED,
ZMQ_GREETING_1,
ZMQ_GREETING_2,
ZMQ_HANDSHAKE,
ZMQ_CONNECTED,
ZMQ_DISCONNECTING,
} m_ZMQConnectionState = ZMQ_NOT_CONNECTED;
std::vector<char> m_ZMQSendBuf;
std::vector<char> m_ZMQRecvBuf;
};

View file

@ -7,8 +7,8 @@
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* 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 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 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
@ -144,6 +144,50 @@ void xmrig::Job::setDiff(uint64_t diff)
}
void xmrig::Job::setSigKey(const char *sig_key)
{
constexpr const size_t size = 64;
if (!sig_key || strlen(sig_key) != size * 2) {
return;
}
# ifndef XMRIG_PROXY_PROJECT
const auto buf = Cvt::fromHex(sig_key, size * 2);
if (buf.size() == size) {
setEphemeralKeys(buf.data(), buf.data() + 32);
}
# else
m_rawSigKey = sig_key;
# endif
}
uint32_t xmrig::Job::getNumTransactions() const
{
if (m_algorithm.family() > Algorithm::RANDOM_X) {
return 0;
}
uint32_t num_transactions = 0;
// Monero (and some other coins) has the number of transactions encoded as varint in the end of hashing blob
const size_t expected_tx_offset = (m_algorithm == Algorithm::RX_WOW) ? 141 : 75;
if ((m_size > expected_tx_offset) && (m_size <= expected_tx_offset + 4)) {
for (size_t i = expected_tx_offset, k = 0; i < m_size; ++i, k += 7) {
const uint8_t b = m_blob[i];
num_transactions |= static_cast<uint32_t>(b & 0x7F) << k;
if ((b & 0x80) == 0) {
break;
}
}
}
return num_transactions;
}
void xmrig::Job::copy(const Job &other)
{
m_algorithm = other.m_algorithm;
@ -164,6 +208,7 @@ void xmrig::Job::copy(const Job &other)
# ifdef XMRIG_PROXY_PROJECT
m_rawSeedHash = other.m_rawSeedHash;
m_rawSigKey = other.m_rawSigKey;
memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob));
memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget));
@ -181,6 +226,8 @@ void xmrig::Job::copy(const Job &other)
m_minerTxPrefix = other.m_minerTxPrefix;
m_minerTxEphPubKeyOffset = other.m_minerTxEphPubKeyOffset;
m_minerTxPubKeyOffset = other.m_minerTxPubKeyOffset;
m_minerTxExtraNonceOffset = other.m_minerTxExtraNonceOffset;
m_minerTxExtraNonceSize = other.m_minerTxExtraNonceSize;
m_minerTxMerkleTreeBranch = other.m_minerTxMerkleTreeBranch;
# else
memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey));
@ -215,6 +262,7 @@ void xmrig::Job::move(Job &&other)
# ifdef XMRIG_PROXY_PROJECT
m_rawSeedHash = std::move(other.m_rawSeedHash);
m_rawSigKey = std::move(other.m_rawSigKey);
memcpy(m_rawBlob, other.m_rawBlob, sizeof(m_rawBlob));
memcpy(m_rawTarget, other.m_rawTarget, sizeof(m_rawTarget));
@ -229,10 +277,13 @@ void xmrig::Job::move(Job &&other)
memcpy(m_viewSecretKey, other.m_viewSecretKey, sizeof(m_viewSecretKey));
memcpy(m_spendPublicKey, other.m_spendPublicKey, sizeof(m_spendPublicKey));
memcpy(m_viewPublicKey, other.m_viewPublicKey, sizeof(m_viewPublicKey));
m_minerTxPrefix = std::move(other.m_minerTxPrefix);
m_minerTxEphPubKeyOffset = other.m_minerTxEphPubKeyOffset;
m_minerTxPubKeyOffset = other.m_minerTxPubKeyOffset;
m_minerTxMerkleTreeBranch = std::move(other.m_minerTxMerkleTreeBranch);
m_minerTxPrefix = std::move(other.m_minerTxPrefix);
m_minerTxEphPubKeyOffset = other.m_minerTxEphPubKeyOffset;
m_minerTxPubKeyOffset = other.m_minerTxPubKeyOffset;
m_minerTxExtraNonceOffset = other.m_minerTxExtraNonceOffset;
m_minerTxExtraNonceSize = other.m_minerTxExtraNonceSize;
m_minerTxMerkleTreeBranch = std::move(other.m_minerTxMerkleTreeBranch);
# else
memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey));
memcpy(m_ephSecretKey, other.m_ephSecretKey, sizeof(m_ephSecretKey));
@ -245,26 +296,35 @@ void xmrig::Job::move(Job &&other)
#ifdef XMRIG_PROXY_PROJECT
void xmrig::Job::setSpendSecretKey(uint8_t* key)
void xmrig::Job::setSpendSecretKey(const uint8_t *key)
{
m_hasMinerSignature = true;
memcpy(m_spendSecretKey, key, sizeof(m_spendSecretKey));
xmrig::derive_view_secret_key(m_spendSecretKey, m_viewSecretKey);
xmrig::secret_key_to_public_key(m_spendSecretKey, m_spendPublicKey);
xmrig::secret_key_to_public_key(m_viewSecretKey, m_viewPublicKey);
derive_view_secret_key(m_spendSecretKey, m_viewSecretKey);
secret_key_to_public_key(m_spendSecretKey, m_spendPublicKey);
secret_key_to_public_key(m_viewSecretKey, m_viewPublicKey);
}
void xmrig::Job::setMinerTx(const uint8_t* begin, const uint8_t* end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, const Buffer& minerTxMerkleTreeBranch)
void xmrig::Job::setMinerTx(const uint8_t *begin, const uint8_t *end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, size_t minerTxExtraNonceOffset, size_t minerTxExtraNonceSize, const Buffer &minerTxMerkleTreeBranch)
{
m_minerTxPrefix.assign(begin, end);
m_minerTxEphPubKeyOffset = minerTxEphPubKeyOffset;
m_minerTxPubKeyOffset = minerTxPubKeyOffset;
m_minerTxMerkleTreeBranch = minerTxMerkleTreeBranch;
m_minerTxEphPubKeyOffset = minerTxEphPubKeyOffset;
m_minerTxPubKeyOffset = minerTxPubKeyOffset;
m_minerTxExtraNonceOffset = minerTxExtraNonceOffset;
m_minerTxExtraNonceSize = minerTxExtraNonceSize;
m_minerTxMerkleTreeBranch = minerTxMerkleTreeBranch;
}
void xmrig::Job::generateHashingBlob(String& blob, String& signatureData) const
void xmrig::Job::setExtraNonceInMinerTx(uint32_t extra_nonce)
{
memcpy(m_minerTxPrefix.data() + m_minerTxExtraNonceOffset, &extra_nonce, std::min(m_minerTxExtraNonceSize, sizeof(uint32_t)));
}
void xmrig::Job::generateSignatureData(String &signatureData) const
{
uint8_t* eph_public_key = m_minerTxPrefix.data() + m_minerTxEphPubKeyOffset;
uint8_t* txkey_pub = m_minerTxPrefix.data() + m_minerTxPubKeyOffset;
@ -285,15 +345,23 @@ void xmrig::Job::generateHashingBlob(String& blob, String& signatureData) const
generate_key_derivation(txkey_pub, m_viewSecretKey, derivation);
derive_secret_key(derivation, 0, m_spendSecretKey, buf + 64);
signatureData = xmrig::Cvt::toHex(buf, sizeof(buf));
signatureData = Cvt::toHex(buf, sizeof(buf));
}
void xmrig::Job::generateHashingBlob(String &blob) const
{
uint8_t root_hash[32];
const uint8_t* p = m_minerTxPrefix.data();
xmrig::BlockTemplate::CalculateRootHash(p, p + m_minerTxPrefix.size(), m_minerTxMerkleTreeBranch, root_hash);
BlockTemplate::CalculateRootHash(p, p + m_minerTxPrefix.size(), m_minerTxMerkleTreeBranch, root_hash);
uint64_t root_hash_offset = nonceOffset() + nonceSize();
if (m_hasMinerSignature) {
root_hash_offset += BlockTemplate::SIGNATURE_SIZE + 2 /* vote */;
}
blob = rawBlob();
const uint64_t offset = nonceOffset() + nonceSize() + BlockTemplate::SIGNATURE_SIZE + 2 /* vote */;
xmrig::Cvt::toHex(blob.data() + offset * 2, 64, root_hash, 32);
Cvt::toHex(blob.data() + root_hash_offset * 2, 64, root_hash, BlockTemplate::HASH_SIZE);
}

View file

@ -7,8 +7,8 @@
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* 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 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2021 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
@ -63,6 +63,7 @@ public:
bool setSeedHash(const char *hash);
bool setTarget(const char *target);
void setDiff(uint64_t diff);
void setSigKey(const char *sig_key);
inline bool isNicehash() const { return m_nicehash; }
inline bool isValid() const { return (m_size > 0 && m_diff > 0) || !m_poolWallet.isEmpty(); }
@ -102,6 +103,7 @@ public:
inline const char *rawBlob() const { return m_rawBlob; }
inline const char *rawTarget() const { return m_rawTarget; }
inline const String &rawSeedHash() const { return m_rawSeedHash; }
inline const String &rawSigKey() const { return m_rawSigKey; }
# endif
static inline uint64_t toDiff(uint64_t target) { return target ? (0xFFFFFFFFFFFFFFFFULL / target) : 0; }
@ -117,13 +119,15 @@ public:
# endif
# ifdef XMRIG_PROXY_PROJECT
void setSpendSecretKey(uint8_t* key);
void setMinerTx(const uint8_t* begin, const uint8_t* end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, const Buffer& minerTxMerkleTreeBranch);
void generateHashingBlob(String& blob, String& signatureData) const;
void setSpendSecretKey(const uint8_t* key);
void setMinerTx(const uint8_t* begin, const uint8_t* end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, size_t minerTxExtraNonceOffset, size_t minerTxExtraNonceSize, const Buffer& minerTxMerkleTreeBranch);
void setExtraNonceInMinerTx(uint32_t extra_nonce);
void generateSignatureData(String& signatureData) const;
void generateHashingBlob(String& blob) const;
# else
inline const uint8_t* ephSecretKey() const { return m_hasMinerSignature ? m_ephSecretKey : nullptr; }
inline void setEphemeralKeys(uint8_t* pub_key, uint8_t* sec_key)
inline void setEphemeralKeys(const uint8_t *pub_key, const uint8_t *sec_key)
{
m_hasMinerSignature = true;
memcpy(m_ephPublicKey, pub_key, sizeof(m_ephSecretKey));
@ -135,6 +139,8 @@ public:
inline bool hasMinerSignature() const { return m_hasMinerSignature; }
uint32_t getNumTransactions() const;
private:
void copy(const Job &other);
void move(Job &&other);
@ -158,15 +164,18 @@ private:
char m_rawBlob[kMaxBlobSize * 2 + 8]{};
char m_rawTarget[24]{};
String m_rawSeedHash;
String m_rawSigKey;
// Miner signatures
uint8_t m_spendSecretKey[32];
uint8_t m_viewSecretKey[32];
uint8_t m_spendPublicKey[32];
uint8_t m_viewPublicKey[32];
uint8_t m_spendSecretKey[32]{};
uint8_t m_viewSecretKey[32]{};
uint8_t m_spendPublicKey[32]{};
uint8_t m_viewPublicKey[32]{};
mutable Buffer m_minerTxPrefix;
size_t m_minerTxEphPubKeyOffset = 0;
size_t m_minerTxPubKeyOffset = 0;
size_t m_minerTxExtraNonceOffset = 0;
size_t m_minerTxExtraNonceSize = 0;
Buffer m_minerTxMerkleTreeBranch;
# else
// Miner signatures

View file

@ -66,6 +66,7 @@ const char *Pool::kAlgo = "algo";
const char *Pool::kCoin = "coin";
const char *Pool::kDaemon = "daemon";
const char *Pool::kDaemonPollInterval = "daemon-poll-interval";
const char *Pool::kDaemonZMQPort = "daemon-zmq-port";
const char *Pool::kEnabled = "enabled";
const char *Pool::kFingerprint = "tls-fingerprint";
const char *Pool::kKeepalive = "keepalive";
@ -127,6 +128,7 @@ xmrig::Pool::Pool(const rapidjson::Value &object) :
m_coin = Json::getString(object, kCoin);
m_daemon = Json::getString(object, kSelfSelect);
m_proxy = Json::getValue(object, kSOCKS5);
m_zmqPort = Json::getInt(object, kDaemonZMQPort, m_zmqPort);
m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true));
m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash) || m_url.host().contains(kNicehashHost));
@ -301,6 +303,7 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
if (m_mode == MODE_DAEMON) {
obj.AddMember(StringRef(kDaemonPollInterval), m_pollInterval, allocator);
obj.AddMember(StringRef(kDaemonZMQPort), m_zmqPort, allocator);
}
else {
obj.AddMember(StringRef(kSelfSelect), m_daemon.url().toJSON(), allocator);
@ -336,6 +339,9 @@ void xmrig::Pool::print() const
LOG_NOTICE("url: %s", url().data());
LOG_DEBUG ("host: %s", host().data());
LOG_DEBUG ("port: %d", static_cast<int>(port()));
if (m_zmqPort >= 0) {
LOG_DEBUG("zmq-port: %d", m_zmqPort);
}
LOG_DEBUG ("user: %s", m_user.data());
LOG_DEBUG ("pass: %s", m_password.data());
LOG_DEBUG ("rig-id %s", m_rigId.data());

View file

@ -72,6 +72,7 @@ public:
static const char *kUrl;
static const char *kUser;
static const char* kSpendSecretKey;
static const char* kDaemonZMQPort;
static const char *kNicehashHost;
constexpr static int kKeepAliveTimeout = 60;
@ -107,6 +108,7 @@ public:
inline int keepAlive() const { return m_keepAlive; }
inline Mode mode() const { return m_mode; }
inline uint16_t port() const { return m_url.port(); }
inline int zmq_port() const { return m_zmqPort; }
inline uint64_t pollInterval() const { return m_pollInterval; }
inline void setAlgo(const Algorithm &algorithm) { m_algorithm = algorithm; }
inline void setPassword(const String &password) { m_password = password; }
@ -155,6 +157,7 @@ private:
uint64_t m_pollInterval = kDefaultPollInterval;
Url m_daemon;
Url m_url;
int m_zmqPort = -1;
# ifdef XMRIG_FEATURE_BENCHMARK
std::shared_ptr<BenchConfig> m_benchmark;

37
src/base/tools/bswap_64.h Normal file
View file

@ -0,0 +1,37 @@
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 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/>.
*/
#ifndef XMRIG_BSWAP_64_H
#define XMRIG_BSWAP_64_H
#ifdef _MSC_VER
#include <stdlib.h>
#define bswap_64(x) _byteswap_uint64(x)
#elif defined __GNUC__
#define bswap_64(x) __builtin_bswap64(x)
#else
#include <byteswap.h>
#endif
#endif /* XMRIG_BSWAP_64_H */

View file

@ -61,6 +61,8 @@ public:
inline size_t index() const { return m_index; }
inline void skip(size_t N) { m_index += N; }
private:
inline bool getByte(uint8_t& data)
{

View file

@ -86,13 +86,35 @@ bool BlockTemplate::Init(const String& blockTemplate, Coin coin)
ar(eph_public_key);
ar(extra_size);
tx_pubkey_index = ar.index() + 1;
const uint64_t tx_extra_index = ar.index();
ar.readItems(extra, extra_size);
// First thing in tx_extra must be TX_EXTRA_TAG_PUBKEY
if (extra[0] != 0x01)
return false;
CBlobReader ar_extra(extra.data(), extra_size);
tx_extra_nonce_size = 0;
tx_extra_nonce_index = 0;
while (ar_extra.index() < extra_size) {
uint64_t extra_tag = 0;
ar_extra(extra_tag);
switch (extra_tag) {
case 0x01: // TX_EXTRA_TAG_PUBKEY
tx_pubkey_index = tx_extra_index + ar_extra.index();
ar_extra.skip(KEY_SIZE);
break;
case 0x02: // TX_EXTRA_NONCE
ar_extra(tx_extra_nonce_size);
tx_extra_nonce_index = tx_extra_index + ar_extra.index();
ar_extra.skip(tx_extra_nonce_size);
break;
default:
return false; // TODO: handle other tags
}
}
miner_tx_prefix_end_index = ar.index();
// Prefix end

View file

@ -42,6 +42,8 @@ struct BlockTemplate
Buffer raw_blob;
size_t eph_public_key_index;
size_t tx_pubkey_index;
uint64_t tx_extra_nonce_size;
size_t tx_extra_nonce_index;
size_t miner_tx_prefix_begin_index;
size_t miner_tx_prefix_end_index;

View file

@ -195,6 +195,9 @@ void xmrig::ConfigTransform::transform(rapidjson::Document &doc, int key, const
case IConfig::RandomXCacheQoSKey: /* --cache-qos */
return set(doc, RxConfig::kField, RxConfig::kCacheQoS, true);
case IConfig::HugePagesJitKey: /* --huge-pages-jit */
return set(doc, CpuConfig::kField, CpuConfig::kHugePagesJit, true);
# endif
# ifdef XMRIG_FEATURE_OPENCL

View file

@ -52,6 +52,7 @@ static const option options[] = {
{ "daemon-poll-interval", 1, nullptr, IConfig::DaemonPollKey },
{ "self-select", 1, nullptr, IConfig::SelfSelectKey },
{ "submit-to-origin", 0, nullptr, IConfig::SubmitToOriginKey },
{ "daemon-zmq-port", 1, nullptr, IConfig::DaemonZMQPortKey },
# endif
{ "av", 1, nullptr, IConfig::AVKey },
{ "background", 0, nullptr, IConfig::BackgroundKey },
@ -68,6 +69,8 @@ static const option options[] = {
{ "no-huge-pages", 0, nullptr, IConfig::HugePagesKey },
{ "no-hugepages", 0, nullptr, IConfig::HugePagesKey },
{ "hugepage-size", 1, nullptr, IConfig::HugePageSizeKey },
{ "huge-pages-jit", 0, nullptr, IConfig::HugePagesJitKey },
{ "hugepages-jit", 0, nullptr, IConfig::HugePagesJitKey },
{ "pass", 1, nullptr, IConfig::PasswordKey },
{ "print-time", 1, nullptr, IConfig::PrintTimeKey },
{ "retries", 1, nullptr, IConfig::RetriesKey },

View file

@ -88,6 +88,9 @@ static inline const std::string &usage()
u += " --no-huge-pages disable huge pages support\n";
# ifdef XMRIG_OS_LINUX
u += " --hugepage-size=N custom hugepage size in kB\n";
# endif
# ifdef XMRIG_ALGO_RANDOMX
u += " --huge-pages-jit enable huge pages support for RandomX JIT code\n";
# endif
u += " --asm=ASM ASM optimizations, possible values: auto, none, intel, ryzen, bulldozer\n";

View file

@ -30,6 +30,7 @@
#include "crypto/astrobwt/AstroBWT.h"
#include "backend/cpu/Cpu.h"
#include "base/crypto/sha3.h"
#include "base/tools/bswap_64.h"
#include "crypto/cn/CryptoNight.h"
@ -54,21 +55,6 @@ __attribute__((ms_abi))
void SHA3_256_AVX2_ASM(const void* in, size_t inBytes, void* out);
#endif
#ifdef _MSC_VER
#include <stdlib.h>
#define bswap_64(x) _byteswap_uint64(x)
#elif defined __GNUC__
#define bswap_64(x) __builtin_bswap64(x)
#else
#include <byteswap.h>
#endif
#ifdef XMRIG_ARM
extern "C" {
#include "salsa20_ref/ecrypt-sync.h"

View file

@ -230,6 +230,10 @@ void xmrig::DmiMemory::setId(const char *slot, const char *bank)
m_slot = slot;
m_bank = bank;
if (!slot || !bank) {
return;
}
try {
std::cmatch cm;
if (std::regex_match(slot, cm, std::regex("^Channel([A-Z])[-_]DIMM(\\d+)$", std::regex_constants::icase))) {

View file

@ -137,9 +137,14 @@ void xmrig::Network::onActive(IStrategy *strategy, IClient *client)
}
# endif
char zmq_buf[32] = {};
if (client->pool().zmq_port() >= 0) {
snprintf(zmq_buf, sizeof(zmq_buf), " (ZMQ:%d)", client->pool().zmq_port());
}
const char *tlsVersion = client->tlsVersion();
LOG_INFO("%s " WHITE_BOLD("use %s ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " " BLACK_BOLD("%s"),
Tags::network(), client->mode(), pool.host().data(), pool.port(), tlsVersion ? tlsVersion : "", client->ip().data());
LOG_INFO("%s " WHITE_BOLD("use %s ") CYAN_BOLD("%s:%d%s ") GREEN_BOLD("%s") " " BLACK_BOLD("%s"),
Tags::network(), client->mode(), pool.host().data(), pool.port(), zmq_buf, tlsVersion ? tlsVersion : "", client->ip().data());
const char *fingerprint = client->tlsFingerprint();
if (fingerprint != nullptr) {
@ -269,11 +274,22 @@ void xmrig::Network::setJob(IClient *client, const Job &job, bool donate)
if (!BenchState::size())
# endif
{
uint64_t diff = job.diff();;
uint64_t diff = job.diff();
const char *scale = NetworkState::scaleDiff(diff);
LOG_INFO("%s " MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d") " diff " WHITE_BOLD("%" PRIu64 "%s") " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64),
Tags::network(), client->pool().host().data(), client->pool().port(), diff, scale, job.algorithm().shortName(), job.height());
char zmq_buf[32] = {};
if (client->pool().zmq_port() >= 0) {
snprintf(zmq_buf, sizeof(zmq_buf), " (ZMQ:%d)", client->pool().zmq_port());
}
char tx_buf[32] = {};
const uint32_t num_transactions = job.getNumTransactions();
if (num_transactions > 0) {
snprintf(tx_buf, sizeof(tx_buf), " (%u tx)", num_transactions);
}
LOG_INFO("%s " MAGENTA_BOLD("new job") " from " WHITE_BOLD("%s:%d%s") " diff " WHITE_BOLD("%" PRIu64 "%s") " algo " WHITE_BOLD("%s") " height " WHITE_BOLD("%" PRIu64) "%s",
Tags::network(), client->pool().host().data(), client->pool().port(), zmq_buf, diff, scale, job.algorithm().shortName(), job.height(), tx_buf);
}
if (!donate && m_donate) {

View file

@ -28,15 +28,15 @@
#define APP_ID "xmrig"
#define APP_NAME "XMRig"
#define APP_DESC "XMRig miner"
#define APP_VERSION "6.13.1"
#define APP_VERSION "6.14.0-dev"
#define APP_DOMAIN "xmrig.com"
#define APP_SITE "www.xmrig.com"
#define APP_COPYRIGHT "Copyright (C) 2016-2021 xmrig.com"
#define APP_KIND "miner"
#define APP_VER_MAJOR 6
#define APP_VER_MINOR 13
#define APP_VER_PATCH 1
#define APP_VER_MINOR 14
#define APP_VER_PATCH 0
#ifdef _MSC_VER
# if (_MSC_VER >= 1920)