From 460d9c75c5ecfb0c9db37285d3bebea1aca33168 Mon Sep 17 00:00:00 2001 From: XMRig Date: Wed, 18 Aug 2021 13:36:50 +0700 Subject: [PATCH] Add global wallet address parser for DaemonClient. --- src/base/kernel/interfaces/IClient.h | 16 ++- src/base/net/stratum/BaseClient.cpp | 14 +-- src/base/net/stratum/BaseClient.h | 10 +- src/base/net/stratum/DaemonClient.cpp | 143 ++++++++++++++------------ src/base/net/stratum/DaemonClient.h | 40 +++---- src/base/net/stratum/Pool.cpp | 4 - 6 files changed, 110 insertions(+), 117 deletions(-) diff --git a/src/base/kernel/interfaces/IClient.h b/src/base/kernel/interfaces/IClient.h index 456d603d..6cf4ff03 100644 --- a/src/base/kernel/interfaces/IClient.h +++ b/src/base/kernel/interfaces/IClient.h @@ -1,12 +1,6 @@ /* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * 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 @@ -27,6 +21,7 @@ #include "3rdparty/rapidjson/fwd.h" +#include "base/tools/Object.h" #include @@ -46,6 +41,8 @@ class String; class IClient { public: + XMRIG_DISABLE_COPY_MOVE(IClient) + enum Extension { EXT_ALGO, EXT_NICEHASH, @@ -57,7 +54,8 @@ public: using Callback = std::function; - virtual ~IClient() = default; + IClient() = default; + virtual ~IClient() = default; virtual bool disconnect() = 0; virtual bool hasExtension(Extension extension) const noexcept = 0; diff --git a/src/base/net/stratum/BaseClient.cpp b/src/base/net/stratum/BaseClient.cpp index 12b7ca76..7c9a728d 100644 --- a/src/base/net/stratum/BaseClient.cpp +++ b/src/base/net/stratum/BaseClient.cpp @@ -1,12 +1,6 @@ /* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * 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,8 +16,8 @@ * along with this program. If not, see . */ - #include "base/net/stratum/BaseClient.h" +#include "3rdparty/fmt/core.h" #include "3rdparty/rapidjson/document.h" #include "base/io/Env.h" #include "base/io/log/Log.h" @@ -58,7 +52,7 @@ void xmrig::BaseClient::setPool(const Pool &pool) m_user = Env::expand(pool.user()); m_password = Env::expand(pool.password()); m_rigId = Env::expand(pool.rigId()); - m_tag = std::string(Tags::network()) + " " CYAN_BOLD_S + m_pool.url().data() + CLEAR; + m_tag = fmt::format("{} " CYAN_BOLD("{}"), Tags::network(), m_pool.url().data()); } diff --git a/src/base/net/stratum/BaseClient.h b/src/base/net/stratum/BaseClient.h index 0a87fedb..53fa59f7 100644 --- a/src/base/net/stratum/BaseClient.h +++ b/src/base/net/stratum/BaseClient.h @@ -1,12 +1,6 @@ /* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * 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 diff --git a/src/base/net/stratum/DaemonClient.cpp b/src/base/net/stratum/DaemonClient.cpp index c9af2801..5cea361d 100644 --- a/src/base/net/stratum/DaemonClient.cpp +++ b/src/base/net/stratum/DaemonClient.cpp @@ -24,6 +24,9 @@ */ +#include + + #include "base/net/stratum/DaemonClient.h" #include "3rdparty/rapidjson/document.h" #include "3rdparty/rapidjson/error/en.h" @@ -42,7 +45,6 @@ #include "base/tools/Cvt.h" #include "base/tools/Timer.h" #include "base/tools/cryptonote/Signatures.h" -#include "base/tools/cryptonote/WalletAddress.h" #include "net/JobResult.h" @@ -181,12 +183,28 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result) void xmrig::DaemonClient::connect() { - if ((m_pool.algorithm() == Algorithm::ASTROBWT_DERO) || (m_pool.coin() == Coin::DERO)) { - m_apiVersion = API_DERO; - } + auto connectError = [this](const char *message) { + if (!isQuiet()) { + LOG_ERR("%s " RED("connect error: ") RED_BOLD("\"%s\""), tag(), message); + } + + retry(); + }; setState(ConnectingState); + if (!m_walletAddress.isValid()) { + return connectError("Invalid wallet address."); + } + + if (!m_coin.isValid() && !m_pool.algorithm().isValid()) { + return connectError("Invalid algorithm."); + } + + if ((m_pool.algorithm() == Algorithm::ASTROBWT_DERO) || (m_coin == Coin::DERO)) { + m_apiVersion = API_DERO; + } + if (m_pool.zmq_port() >= 0) { m_dns = Dns::resolve(m_pool.host(), this); } @@ -203,6 +221,20 @@ void xmrig::DaemonClient::connect(const Pool &pool) } +void xmrig::DaemonClient::setPool(const Pool &pool) +{ + BaseClient::setPool(pool); + + m_walletAddress.decode(m_user); + + m_coin = pool.coin().isValid() ? pool.coin() : m_walletAddress.coin(); + + if (!m_coin.isValid() && pool.algorithm() == Algorithm::RX_WOW) { + m_coin = Coin::WOWNERO; + } +} + + void xmrig::DaemonClient::onHttpData(const HttpData &data) { if (data.status != 200) { @@ -219,7 +251,7 @@ void xmrig::DaemonClient::onHttpData(const HttpData &data) rapidjson::Document doc; if (doc.Parse(data.body.c_str()).HasParseError()) { if (!isQuiet()) { - LOG_ERR("[%s:%d] JSON decode failed: \"%s\"", m_pool.host().data(), m_pool.port(), rapidjson::GetParseError_En(doc.GetParseError())); + LOG_ERR("%s " RED("JSON decode failed: ") RED_BOLD("\"%s\""), tag(), rapidjson::GetParseError_En(doc.GetParseError())); } return retry(); @@ -284,7 +316,7 @@ void xmrig::DaemonClient::onTimer(const Timer *) } -void xmrig::DaemonClient::onResolved(const DnsRecords& records, int status, const char* error) +void xmrig::DaemonClient::onResolved(const DnsRecords &records, int status, const char* error) { m_dns.reset(); @@ -297,14 +329,14 @@ void xmrig::DaemonClient::onResolved(const DnsRecords& records, int status, cons return; } - if (m_ZMQSocket) { - delete m_ZMQSocket; - } - const auto& record = records.get(); + delete m_ZMQSocket; + + + const auto &record = records.get(); m_ip = record.ip(); - uv_connect_t* req = new uv_connect_t; + auto req = new uv_connect_t; req->data = m_storage.ptr(m_key); m_ZMQSocket = new uv_tcp_t; @@ -329,26 +361,26 @@ bool xmrig::DaemonClient::isOutdated(uint64_t height, const char *hash) const bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) { + auto jobError = [this, code](const char *message) { + if (!isQuiet()) { + LOG_ERR("%s " RED("job error: ") RED_BOLD("\"%s\""), tag(), message); + } + + *code = 1; + + return false; + }; + Job job(false, m_pool.algorithm(), String()); String blocktemplate = Json::getString(params, kBlocktemplateBlob); if (blocktemplate.isNull()) { - LOG_ERR("Empty block template received from daemon"); - *code = 1; - return false; + return jobError("Empty block template received from daemon."); } - Coin pool_coin = m_pool.coin(); - - if (!pool_coin.isValid() && (m_pool.algorithm() == Algorithm::RX_WOW)) { - pool_coin = Coin::WOWNERO; - } - - if (!m_blocktemplate.Init(blocktemplate, pool_coin)) { - LOG_ERR("Invalid block template received from daemon"); - *code = 2; - return false; + if (!m_blocktemplate.Init(blocktemplate, m_coin)) { + return jobError("Invalid block template received from daemon."); } # ifdef XMRIG_PROXY_PROJECT @@ -368,29 +400,21 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) if (m_blocktemplate.has_miner_signature) { if (m_pool.spendSecretKey().isEmpty()) { - LOG_ERR("Secret spend key is not set"); - *code = 4; - return false; + return jobError("Secret spend key is not set."); } if (m_pool.spendSecretKey().size() != 64) { - LOG_ERR("Secret spend key has invalid length. It must be 64 hex characters."); - *code = 5; - return false; + return jobError("Secret spend key has invalid length. It must be 64 hex characters."); } uint8_t secret_spendkey[32]; if (!Cvt::fromHex(secret_spendkey, 32, m_pool.spendSecretKey(), 64)) { - LOG_ERR("Secret spend key is not a valid hex data."); - *code = 6; - return false; + return jobError("Secret spend key is not a valid hex data."); } uint8_t public_spendkey[32]; if (!secret_key_to_public_key(secret_spendkey, public_spendkey)) { - LOG_ERR("Secret spend key is invalid."); - *code = 7; - return false; + return jobError("Secret spend key is invalid."); } # ifdef XMRIG_PROXY_PROJECT @@ -401,35 +425,24 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) uint8_t public_viewkey[32]; if (!secret_key_to_public_key(secret_viewkey, public_viewkey)) { - LOG_ERR("Secret view key is invalid."); - *code = 8; - return false; + return jobError("Secret view key is invalid."); } uint8_t derivation[32]; if (!generate_key_derivation(m_blocktemplate.raw_blob.data() + m_blocktemplate.tx_pubkey_index, secret_viewkey, derivation)) { - LOG_ERR("Failed to generate key derivation for miner signature."); - *code = 9; - return false; + return jobError("Failed to generate key derivation for miner signature."); } - WalletAddress user_address; - if (!user_address.decode(m_pool.user())) { - LOG_ERR("Invalid wallet address."); - *code = 10; - return false; + if (!m_walletAddress.decode(m_pool.user())) { + return jobError("Invalid wallet address."); } - if (memcmp(user_address.spendKey(), public_spendkey, sizeof(public_spendkey)) != 0) { - LOG_ERR("Wallet address and spend key don't match."); - *code = 11; - return false; + if (memcmp(m_walletAddress.spendKey(), public_spendkey, sizeof(public_spendkey)) != 0) { + return jobError("Wallet address and spend key don't match."); } - if (memcmp(user_address.viewKey(), public_viewkey, sizeof(public_viewkey)) != 0) { - LOG_ERR("Wallet address and view key don't match."); - *code = 12; - return false; + if (memcmp(m_walletAddress.viewKey(), public_viewkey, sizeof(public_viewkey)) != 0) { + return jobError("Wallet address and view key don't match."); } uint8_t eph_secret_key[32]; @@ -444,8 +457,8 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code) Cvt::toHex(m_blockhashingblob.data() + offset * 2, kBlobReserveSize * 2, Cvt::randomBytes(kBlobReserveSize).data(), kBlobReserveSize); } - if (pool_coin.isValid()) { - job.setAlgorithm(pool_coin.algorithm(m_blocktemplate.major_version)); + if (m_coin.isValid()) { + job.setAlgorithm(m_coin.algorithm(m_blocktemplate.major_version)); } if (!job.setBlob(m_blockhashingblob)) { @@ -594,7 +607,6 @@ void xmrig::DaemonClient::send(const char *path) void xmrig::DaemonClient::setState(SocketState state) { - assert(m_state != state); if (m_state == state) { return; } @@ -735,10 +747,9 @@ void xmrig::DaemonClient::ZMQRead(ssize_t nread, const uv_buf_t* buf) m_ZMQConnectionState = ZMQ_GREETING_2; break; } - else { - LOG_ERR("%s " RED("ZMQ handshake failed: invalid greeting format"), tag()); - ZMQClose(); - } + + LOG_ERR("%s " RED("ZMQ handshake failed: invalid greeting format"), tag()); + ZMQClose(); } return; @@ -751,10 +762,10 @@ void xmrig::DaemonClient::ZMQRead(ssize_t nread, const uv_buf_t* buf) ZMQWrite(kZMQHandshake, sizeof(kZMQHandshake) - 1); break; } - else { - LOG_ERR("%s " RED("ZMQ handshake failed: invalid greeting format 2"), tag()); - ZMQClose(); - } + + LOG_ERR("%s " RED("ZMQ handshake failed: invalid greeting format 2"), tag()); + ZMQClose(); + } return; diff --git a/src/base/net/stratum/DaemonClient.h b/src/base/net/stratum/DaemonClient.h index 2844d15f..5a6ca8ca 100644 --- a/src/base/net/stratum/DaemonClient.h +++ b/src/base/net/stratum/DaemonClient.h @@ -1,13 +1,7 @@ /* XMRig - * Copyright 2010 Jeff Garzik - * Copyright 2012-2014 pooler - * Copyright 2014 Lucas Jones - * Copyright 2014-2016 Wolf9466 - * Copyright 2016 Jay D Dee - * Copyright 2017-2018 XMR-Stak , - * Copyright 2019 Howard Chu - * Copyright 2018-2020 SChernykh - * Copyright 2016-2020 XMRig , + * Copyright (c) 2019 Howard Chu + * Copyright (c) 2018-2021 SChernykh + * Copyright (c) 2016-2021 XMRig , * * 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 @@ -27,21 +21,25 @@ #define XMRIG_DAEMONCLIENT_H -#include - - #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 "base/tools/cryptonote/BlockTemplate.h" +#include "base/tools/cryptonote/WalletAddress.h" #include +using uv_buf_t = struct uv_buf_t; +using uv_connect_t = struct uv_connect_s; +using uv_handle_t = struct uv_handle_s; +using uv_stream_t = struct uv_stream_s; +using uv_tcp_t = struct uv_tcp_s; + + namespace xmrig { @@ -62,10 +60,11 @@ protected: int64_t submit(const JobResult &result) override; void connect() override; void connect(const Pool &pool) override; + void setPool(const Pool &pool) override; void onHttpData(const HttpData &data) override; void onTimer(const Timer *timer) override; - void onResolved(const DnsRecords& records, int status, const char* error) 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"; } @@ -92,18 +91,19 @@ private: API_DERO, } m_apiVersion = API_MONERO; + BlockTemplate m_blocktemplate; + Coin m_coin; std::shared_ptr m_httpListener; - String m_currentJobId; - String m_blocktemplateStr; String m_blockhashingblob; + String m_blocktemplateRequestHash; + String m_blocktemplateStr; + String m_currentJobId; String m_prevHash; String m_tlsFingerprint; String m_tlsVersion; Timer *m_timer; uint64_t m_blocktemplateRequestHeight = 0; - String m_blocktemplateRequestHash; - - BlockTemplate m_blocktemplate; + WalletAddress m_walletAddress; private: static inline DaemonClient* getClient(void* data) { return m_storage.get(data); } diff --git a/src/base/net/stratum/Pool.cpp b/src/base/net/stratum/Pool.cpp index f11c5e2d..367e6667 100644 --- a/src/base/net/stratum/Pool.cpp +++ b/src/base/net/stratum/Pool.cpp @@ -190,10 +190,6 @@ bool xmrig::Pool::isEnabled() const } # endif - if (m_mode == MODE_DAEMON && (!algorithm().isValid() && !coin().isValid())) { - return false; - } - return m_flags.test(FLAG_ENABLED) && isValid(); }