Sync changes.

This commit is contained in:
XMRig
2022-07-03 00:22:26 +07:00
parent fad041d027
commit fc16801fea
37 changed files with 582 additions and 245 deletions

View File

@@ -68,6 +68,7 @@ set(HEADERS_BASE
src/base/net/tools/MemPool.h
src/base/net/tools/NetBuffer.h
src/base/net/tools/Storage.h
src/base/tools/Alignment.h
src/base/tools/Arguments.h
src/base/tools/Baton.h
src/base/tools/bswap_64.h
@@ -132,6 +133,7 @@ set(SOURCES_BASE
src/base/net/tools/LineReader.cpp
src/base/net/tools/NetBuffer.cpp
src/base/tools/Arguments.cpp
src/base/tools/Chrono.cpp
src/base/tools/cryptonote/BlockTemplate.cpp
src/base/tools/cryptonote/crypto-ops-data.c
src/base/tools/cryptonote/crypto-ops.c
@@ -244,7 +246,7 @@ else()
endif()
if (WITH_KAWPOW)
if (WITH_KAWPOW OR WITH_GHOSTRIDER)
list(APPEND HEADERS_BASE
src/base/net/stratum/AutoClient.h
src/base/net/stratum/EthStratumClient.h

View File

@@ -91,16 +91,16 @@ const char *Algorithm::kAR2_CHUKWA_V2 = "argon2/chukwav2";
const char *Algorithm::kAR2_WRKZ = "argon2/ninja";
#endif
#ifdef XMRIG_ALGO_ASTROBWT
const char *Algorithm::kASTROBWT = "astrobwt";
const char *Algorithm::kASTROBWT_DERO = "astrobwt";
#endif
#ifdef XMRIG_ALGO_KAWPOW
const char *Algorithm::kKAWPOW = "kawpow";
const char *Algorithm::kKAWPOW_RVN = "kawpow";
#endif
#ifdef XMRIG_ALGO_GHOSTRIDER
const char* Algorithm::kGHOSTRIDER = "ghostrider";
const char* Algorithm::kGHOSTRIDER_RTM = "ghostrider";
#endif
#define ALGO_NAME(ALGO) { Algorithm::ALGO, Algorithm::k##ALGO }
#define ALGO_ALIAS(ALGO, NAME) { NAME, Algorithm::ALGO }
@@ -156,13 +156,13 @@ static const std::map<uint32_t, const char *> kAlgorithmNames = {
ALGO_NAME(AR2_WRKZ),
# endif
# ifdef XMRIG_ALGO_ASTROBWT
ALGO_NAME(ASTROBWT_DERO),
# endif
# ifdef XMRIG_ALGO_KAWPOW
ALGO_NAME(KAWPOW_RVN),
# endif
# ifdef XMRIG_ALGO_GHOSTRIDER
ALGO_NAME(GHOSTRIDER_RTM),
# endif
};
@@ -271,13 +271,14 @@ static const std::map<const char *, Algorithm::Id, aliasCompare> kAlgorithmAlias
ALGO_ALIAS_AUTO(AR2_WRKZ), ALGO_ALIAS(AR2_WRKZ, "argon2/wrkz"),
# endif
# ifdef XMRIG_ALGO_ASTROBWT
ALGO_ALIAS_AUTO(ASTROBWT_DERO), ALGO_ALIAS(ASTROBWT_DERO, "astrobwt/dero"),
# endif
# ifdef XMRIG_ALGO_KAWPOW
ALGO_ALIAS_AUTO(KAWPOW_RVN), ALGO_ALIAS(KAWPOW_RVN, "kawpow/rvn"),
# endif
# ifdef XMRIG_ALGO_GHOSTRIDER
ALGO_ALIAS_AUTO(GHOSTRIDER_RTM), ALGO_ALIAS(GHOSTRIDER_RTM, "ghostrider/rtm"),
ALGO_ALIAS(GHOSTRIDER_RTM, "gr"),
# endif
};
@@ -351,8 +352,8 @@ std::vector<xmrig::Algorithm> xmrig::Algorithm::all(const std::function<bool(con
CN_UPX2,
RX_0, RX_WOW, RX_ARQ, RX_GRAFT, RX_SFX, RX_KEVA,
AR2_CHUKWA, AR2_CHUKWA_V2, AR2_WRKZ,
ASTROBWT_DERO,
KAWPOW_RVN
KAWPOW_RVN,
GHOSTRIDER_RTM
};
Algorithms out;

View File

@@ -65,6 +65,13 @@ public:
CN_PICO_0 = 0x63120200, // "cn-pico" CryptoNight-Pico
CN_PICO_TLO = 0x63120274, // "cn-pico/tlo" CryptoNight-Pico (TLO)
CN_UPX2 = 0x63110200, // "cn/upx2" Uplexa (UPX2)
CN_GR_0 = 0x63130100, // "cn/dark" GhostRider
CN_GR_1 = 0x63130101, // "cn/dark-lite" GhostRider
CN_GR_2 = 0x63150102, // "cn/fast" GhostRider
CN_GR_3 = 0x63140103, // "cn/lite" GhostRider
CN_GR_4 = 0x63120104, // "cn/turtle" GhostRider
CN_GR_5 = 0x63120105, // "cn/turtle-lite" GhostRider
GHOSTRIDER_RTM = 0x6c150000, // "ghostrider" GhostRider
RX_0 = 0x72151200, // "rx/0" RandomX (reference configuration).
RX_WOW = 0x72141177, // "rx/wow" RandomWOW (Wownero).
RX_ARQ = 0x72121061, // "rx/arq" RandomARQ (Arqma).
@@ -74,7 +81,6 @@ public:
AR2_CHUKWA = 0x61130000, // "argon2/chukwa" Argon2id (Chukwa).
AR2_CHUKWA_V2 = 0x61140000, // "argon2/chukwav2" Argon2id (Chukwa v2).
AR2_WRKZ = 0x61120000, // "argon2/wrkz" Argon2id (WRKZ)
ASTROBWT_DERO = 0x41000000, // "astrobwt" AstroBWT (Dero)
KAWPOW_RVN = 0x6b0f0000, // "kawpow/rvn" KawPow (RVN)
};
@@ -88,8 +94,8 @@ public:
CN_FEMTO = 0x63110000,
RANDOM_X = 0x72000000,
ARGON2 = 0x61000000,
ASTROBWT = 0x41000000,
KAWPOW = 0x6b000000
KAWPOW = 0x6b000000,
GHOSTRIDER = 0x6c000000
};
static const char *kINVALID;
@@ -147,16 +153,16 @@ public:
static const char *kAR2_WRKZ;
# endif
# ifdef XMRIG_ALGO_ASTROBWT
static const char *kASTROBWT;
static const char *kASTROBWT_DERO;
# endif
# ifdef XMRIG_ALGO_KAWPOW
static const char *kKAWPOW;
static const char *kKAWPOW_RVN;
# endif
# ifdef XMRIG_ALGO_GHOSTRIDER
static const char* kGHOSTRIDER;
static const char* kGHOSTRIDER_RTM;
# endif
inline Algorithm() = default;
inline Algorithm(const char *algo) : m_id(parse(algo)) {}
inline Algorithm(Id id) : m_id(id) {}
@@ -176,16 +182,10 @@ public:
inline Id id() const { return m_id; }
inline size_t l2() const { return l2(m_id); }
inline uint32_t family() const { return family(m_id); }
inline uint32_t maxIntensity() const { return isCN() ? 5 : 1; };
inline uint32_t minIntensity() const { return ((m_id == GHOSTRIDER_RTM) ? 8 : 1); };
inline uint32_t maxIntensity() const { return isCN() ? 5 : ((m_id == GHOSTRIDER_RTM) ? 8 : 1); };
inline size_t l3() const
{
# ifdef XMRIG_ALGO_ASTROBWT
return m_id != ASTROBWT_DERO ? l3(m_id) : 0x100000 * 20;
# else
return l3(m_id);
# endif
}
inline size_t l3() const { return l3(m_id); }
inline bool operator!=(Algorithm::Id id) const { return m_id != id; }
inline bool operator!=(const Algorithm &other) const { return !isEqual(other); }

View File

@@ -45,15 +45,14 @@ struct CoinInfo
static const CoinInfo coinInfo[] = {
{ Algorithm::INVALID, nullptr, nullptr, 0, 0, nullptr },
{ Algorithm::RX_0, "XMR", "Monero", 120, 1000000000000, YELLOW_BG_BOLD( WHITE_BOLD_S " monero ") },
{ Algorithm::CN_R, "SUMO", "Sumokoin", 240, 1000000000, BLUE_BG_BOLD( WHITE_BOLD_S " sumo ") },
{ Algorithm::RX_ARQ, "ARQ", "ArQmA", 120, 1000000000, BLUE_BG_BOLD( WHITE_BOLD_S " arqma ") },
{ Algorithm::ASTROBWT_DERO, "DERO", "DERO", 0, 0, BLUE_BG_BOLD( WHITE_BOLD_S " dero ") },
{ Algorithm::RX_GRAFT, "GRFT", "Graft", 120, 10000000000, BLUE_BG_BOLD( WHITE_BOLD_S " graft ") },
{ Algorithm::RX_KEVA, "KVA", "Kevacoin", 0, 0, MAGENTA_BG_BOLD(WHITE_BOLD_S " keva ") },
{ Algorithm::KAWPOW_RVN, "RVN", "Ravencoin", 0, 0, BLUE_BG_BOLD( WHITE_BOLD_S " raven ") },
{ Algorithm::RX_WOW, "WOW", "Wownero", 300, 100000000000, MAGENTA_BG_BOLD(WHITE_BOLD_S " wownero ") },
{ Algorithm::INVALID, nullptr, nullptr, 0, 0, nullptr },
{ Algorithm::RX_0, "XMR", "Monero", 120, 1000000000000, YELLOW_BG_BOLD( WHITE_BOLD_S " monero ") },
{ Algorithm::CN_R, "SUMO", "Sumokoin", 240, 1000000000, BLUE_BG_BOLD( WHITE_BOLD_S " sumo ") },
{ Algorithm::RX_ARQ, "ARQ", "ArQmA", 120, 1000000000, BLUE_BG_BOLD( WHITE_BOLD_S " arqma ") },
{ Algorithm::RX_GRAFT, "GRFT", "Graft", 120, 10000000000, BLUE_BG_BOLD( WHITE_BOLD_S " graft ") },
{ Algorithm::RX_KEVA, "KVA", "Kevacoin", 0, 0, MAGENTA_BG_BOLD(WHITE_BOLD_S " keva ") },
{ Algorithm::KAWPOW_RVN, "RVN", "Ravencoin", 0, 0, BLUE_BG_BOLD( WHITE_BOLD_S " raven ") },
{ Algorithm::RX_WOW, "WOW", "Wownero", 300, 100000000000, MAGENTA_BG_BOLD(WHITE_BOLD_S " wownero ") },
};

View File

@@ -35,7 +35,6 @@ public:
MONERO,
SUMO,
ARQMA,
DERO,
GRAFT,
KEVA,
RAVEN,

View File

@@ -37,14 +37,14 @@
#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y))))
#endif
const uint64_t keccakf_rndc[24] =
const uint64_t keccakf_rndc[24] =
{
0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
};
@@ -53,10 +53,8 @@ const uint64_t keccakf_rndc[24] =
void xmrig::keccakf(uint64_t st[25], int rounds)
{
int i, j, round;
uint64_t t, bc[5];
for (round = 0; round < rounds; ++round) {
for (int round = 0; round < rounds; ++round) {
uint64_t bc[5];
// Theta
bc[0] = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20];
@@ -65,17 +63,21 @@ void xmrig::keccakf(uint64_t st[25], int rounds)
bc[3] = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
bc[4] = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
for (i = 0; i < 5; ++i) {
t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
st[i ] ^= t;
st[i + 5] ^= t;
st[i + 10] ^= t;
st[i + 15] ^= t;
st[i + 20] ^= t;
#define X(i) { \
const uint64_t t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); \
st[i ] ^= t; \
st[i + 5] ^= t; \
st[i + 10] ^= t; \
st[i + 15] ^= t; \
st[i + 20] ^= t; \
}
X(0); X(1); X(2); X(3); X(4);
#undef X
// Rho Pi
t = st[1];
const uint64_t t = st[1];
st[ 1] = ROTL64(st[ 6], 44);
st[ 6] = ROTL64(st[ 9], 20);
st[ 9] = ROTL64(st[22], 61);
@@ -103,7 +105,7 @@ void xmrig::keccakf(uint64_t st[25], int rounds)
// Chi
// unrolled loop, where only last iteration is different
j = 0;
int j = 0;
bc[0] = st[j ];
bc[1] = st[j + 1];
@@ -155,7 +157,7 @@ void xmrig::keccakf(uint64_t st[25], int rounds)
st[j + 2] ^= (~bc[3]) & bc[4];
st[j + 3] ^= (~bc[4]) & bc[0];
st[j + 4] ^= (~bc[0]) & bc[1];
// Iota
st[0] ^= keccakf_rndc[round];
}
@@ -173,7 +175,7 @@ void xmrig::keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen)
rsiz = sizeof(state_t) == mdlen ? HASH_DATA_AREA : 200 - 2 * mdlen;
rsizw = rsiz / 8;
memset(st, 0, sizeof(st));
for ( ; inlen >= rsiz; inlen -= rsiz, in += rsiz) {

View File

@@ -1,16 +1,16 @@
/* -------------------------------------------------------------------------
* Works when compiled for either 32-bit or 64-bit targets, optimized for
* Works when compiled for either 32-bit or 64-bit targets, optimized for
* 64 bit.
*
* Canonical implementation of Init/Update/Finalize for SHA-3 byte input.
* Canonical implementation of Init/Update/Finalize for SHA-3 byte input.
*
* SHA3-256, SHA3-384, SHA-512 are implemented. SHA-224 can easily be added.
*
* Based on code from http://keccak.noekeon.org/ .
*
* I place the code that I wrote into public domain, free to use.
* I place the code that I wrote into public domain, free to use.
*
* I would appreciate if you give credits to this work if you used it to
* I would appreciate if you give credits to this work if you used it to
* write or test * your code.
*
* Aug 2015. Andrey Jivsov. crypto@brainhub.org
@@ -32,7 +32,7 @@
#define SHA3_TRACE_BUF(format, buf, l, args...)
#endif
/*
/*
* This flag is used to configure "pure" Keccak, as opposed to NIST SHA3.
*/
#define SHA3_USE_KECCAK_FLAG 0x80000000
@@ -108,7 +108,7 @@ sha3_Update(void *priv, void const *bufIn, size_t len)
SHA3_ASSERT(ctx->byteIndex < 8);
SHA3_ASSERT(ctx->wordIndex < sizeof(ctx->s) / sizeof(ctx->s[0]));
if(len < old_tail) { /* have no complete word or haven't started
if(len < old_tail) { /* have no complete word or haven't started
* the word yet */
SHA3_TRACE("because %d<%d, store it and return", (unsigned)len,
(unsigned)old_tail);
@@ -180,7 +180,7 @@ sha3_Update(void *priv, void const *bufIn, size_t len)
}
/* This is simply the 'update' with the padding block.
* The padding block is 0x01 || 0x00* || 0x80. First 0x01 and last 0x80
* The padding block is 0x01 || 0x00* || 0x80. First 0x01 and last 0x80
* bytes are always present, but they can be the same byte.
*/
void const *
@@ -214,7 +214,7 @@ sha3_Finalize(void *priv)
/* Return first bytes of the ctx->s. This conversion is not needed for
* little-endian platforms e.g. wrap with #if !defined(__BYTE_ORDER__)
* || !defined(__ORDER_LITTLE_ENDIAN__) || __BYTE_ORDER__!=__ORDER_LITTLE_ENDIAN__
* || !defined(__ORDER_LITTLE_ENDIAN__) || __BYTE_ORDER__!=__ORDER_LITTLE_ENDIAN__
* ... the conversion below ...
* #endif */
{

View File

@@ -2,18 +2,18 @@
#define SHA3_H
/* -------------------------------------------------------------------------
* Works when compiled for either 32-bit or 64-bit targets, optimized for
* Works when compiled for either 32-bit or 64-bit targets, optimized for
* 64 bit.
*
* Canonical implementation of Init/Update/Finalize for SHA-3 byte input.
* Canonical implementation of Init/Update/Finalize for SHA-3 byte input.
*
* SHA3-256, SHA3-384, SHA-512 are implemented. SHA-224 can easily be added.
*
* Based on code from http://keccak.noekeon.org/ .
*
* I place the code that I wrote into public domain, free to use.
* I place the code that I wrote into public domain, free to use.
*
* I would appreciate if you give credits to this work if you used it to
* I would appreciate if you give credits to this work if you used it to
* write or test * your code.
*
* Aug 2015. Andrey Jivsov. crypto@brainhub.org
@@ -65,9 +65,9 @@ void const *sha3_Finalize(void *priv);
#ifdef __cplusplus
extern "C"
#endif
sha3_return_t sha3_HashBuffer(
sha3_return_t sha3_HashBuffer(
unsigned bitSize, /* 256, 384, 512 */
enum SHA3_FLAGS flags, /* SHA3_FLAGS_NONE or SHA3_FLAGS_KECCAK */
const void *in, unsigned inBytes,
const void *in, unsigned inBytes,
void *out, unsigned outBytes ); /* up to bitSize/8; truncation OK */
#endif

View File

@@ -134,12 +134,12 @@ private:
if (read(chain, config)) {
return config.release();
}
chain.addFile(Process::location(Process::HomeLocation, "." APP_ID ".json"));
if (read(chain, config)) {
return config.release();
}
chain.addFile(Process::location(Process::HomeLocation, ".config" XMRIG_DIR_SEPARATOR APP_ID ".json"));
if (read(chain, config)) {
return config.release();

View File

@@ -152,7 +152,7 @@ xmrig::String xmrig::Process::exepath()
{
size_t size = sizeof(pathBuf);
return uv_exepath(pathBuf, &size) < 0 ? "" : String(pathBuf, size);
return uv_exepath(pathBuf, &size) < 0 ? String("") : String(pathBuf, size);
}

View File

@@ -87,6 +87,7 @@ public:
SpendSecretKey = 1055,
DaemonZMQPortKey = 1056,
HugePagesJitKey = 1057,
RotationKey = 1058,
// xmrig common
CPUPriorityKey = 1021,
@@ -110,8 +111,6 @@ public:
CPUMaxThreadsKey = 1026,
MemoryPoolKey = 1027,
YieldKey = 1030,
AstroBWTMaxSizeKey = 1034,
AstroBWTAVX2Key = 1036,
Argon2ImplKey = 1039,
RandomXCacheQoSKey = 1040,

View File

@@ -28,13 +28,19 @@
namespace xmrig {
static Storage<DnsUvBackend>* storage = nullptr;
Storage<DnsUvBackend>& DnsUvBackend::getStorage()
{
static Storage<DnsUvBackend>* storage = new Storage<DnsUvBackend>();
if (storage == nullptr) storage = new Storage<DnsUvBackend>();
return *storage;
}
void DnsUvBackend::releaseStorage()
{
delete storage;
}
static addrinfo hints{};
@@ -56,6 +62,7 @@ xmrig::DnsUvBackend::DnsUvBackend()
xmrig::DnsUvBackend::~DnsUvBackend()
{
getStorage().release(m_key);
releaseStorage();
}

View File

@@ -62,6 +62,7 @@ private:
uintptr_t m_key;
static Storage<DnsUvBackend>& getStorage();
void releaseStorage();
};

View File

@@ -50,7 +50,7 @@ bool xmrig::AutoClient::parseLogin(const rapidjson::Value &result, int *code)
}
const Algorithm algo(Json::getString(result, "algo"));
if (algo.family() != Algorithm::KAWPOW) {
if (algo.family() != Algorithm::KAWPOW && algo.family() != Algorithm::GHOSTRIDER) {
*code = 6;
return false;
}
@@ -65,6 +65,12 @@ bool xmrig::AutoClient::parseLogin(const rapidjson::Value &result, int *code)
m_mode = ETH_MODE;
setAlgo(algo);
# ifdef XMRIG_ALGO_GHOSTRIDER
if (algo.family() == Algorithm::GHOSTRIDER) {
setExtraNonce2Size(Json::getUint64(result, "extra_nonce2_size"));
}
# endif
return true;
}

View File

@@ -23,6 +23,7 @@
#include <cstdio>
#include <cstring>
#include <utility>
#include <sstream>
#ifdef XMRIG_FEATURE_TLS
@@ -660,7 +661,7 @@ void xmrig::Client::parse(char *line, size_t len)
LOG_DEBUG("[%s] received (%d bytes): \"%.*s\"", url(), len, static_cast<int>(len), line);
if (len < 32 || line[0] != '{') {
if (len < 22 || line[0] != '{') {
if (!isQuiet()) {
LOG_ERR("%s " RED("JSON decode failed"), tag());
}
@@ -683,12 +684,48 @@ void xmrig::Client::parse(char *line, size_t len)
const auto &id = Json::getValue(doc, "id");
const auto &error = Json::getValue(doc, "error");
const char *method = Json::getString(doc, "method");
if (method && strcmp(method, "client.reconnect") == 0) {
const auto &params = Json::getValue(doc, "params");
if (!params.IsArray()) {
LOG_ERR("%s " RED("invalid client.reconnect notification: params is not an array"), tag());
return;
}
auto arr = params.GetArray();
if (arr.Empty()) {
LOG_ERR("%s " RED("invalid client.reconnect notification: params array is empty"), tag());
return;
}
if (arr.Size() != 2) {
LOG_ERR("%s " RED("invalid client.reconnect notification: params array has wrong size"), tag());
return;
}
if (!arr[0].IsString()) {
LOG_ERR("%s " RED("invalid client.reconnect notification: host is not a string"), tag());
return;
}
if (!arr[1].IsString()) {
LOG_ERR("%s " RED("invalid client.reconnect notification: port is not a string"), tag());
return;
}
std::stringstream s;
s << arr[0].GetString() << ":" << arr[1].GetString();
LOG_WARN("%s " YELLOW("client.reconnect to %s"), tag(), s.str().c_str());
setPoolUrl(s.str().c_str());
return reconnect();
}
if (id.IsInt64()) {
return parseResponse(id.GetInt64(), Json::getValue(doc, "result"), error);
}
const char *method = Json::getString(doc, "method");
if (!method) {
return;
}

View File

@@ -84,6 +84,7 @@ protected:
inline const char *url() const { return m_pool.url(); }
inline const String &rpcId() const { return m_rpcId; }
inline void setRpcId(const char *id) { m_rpcId = id; }
inline void setPoolUrl(const char *url) { m_pool.setUrl(url); }
virtual bool parseLogin(const rapidjson::Value &result, int *code);
virtual void login();

View File

@@ -48,8 +48,14 @@
#include "net/JobResult.h"
#ifdef XMRIG_FEATURE_TLS
#include <openssl/ssl.h>
#endif
#include <algorithm>
#include <cassert>
#include <random>
namespace xmrig {
@@ -58,7 +64,9 @@ namespace xmrig {
Storage<DaemonClient> DaemonClient::m_storage;
static const char* kBlocktemplateBlob = "blocktemplate_blob";
static const char* kBlocktemplateBlob = "blocktemplate_blob";
static const char* kBlockhashingBlob = "blockhashing_blob";
static const char* kLastError = "lasterror";
static const char *kGetHeight = "/getheight";
static const char *kGetInfo = "/getinfo";
static const char *kHash = "hash";
@@ -129,7 +137,7 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result)
return -1;
}
char *data = (m_apiVersion == API_DERO) ? m_blockhashingblob.data() : m_blocktemplateStr.data();
char *data = m_blocktemplateStr.data();
const size_t sig_offset = m_job.nonceOffset() + m_job.nonceSize();
@@ -161,13 +169,7 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result)
Document doc(kObjectType);
Value params(kArrayType);
if (m_apiVersion == API_DERO) {
params.PushBack(m_blocktemplateStr.toJSON(), doc.GetAllocator());
params.PushBack(m_blockhashingblob.toJSON(), doc.GetAllocator());
}
else {
params.PushBack(m_blocktemplateStr.toJSON(), doc.GetAllocator());
}
params.PushBack(m_blocktemplateStr.toJSON(), doc.GetAllocator());
JsonRequest::create(doc, m_sequence, "submitblock", params);
@@ -193,16 +195,16 @@ void xmrig::DaemonClient::connect()
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.algorithm().isValid()) {
m_pool.setAlgo(m_coin.algorithm());
}
if ((m_apiVersion == API_MONERO) && !m_walletAddress.isValid()) {
return connectError("Invalid wallet address.");
}
if (m_pool.zmq_port() >= 0) {
@@ -306,12 +308,7 @@ void xmrig::DaemonClient::onTimer(const Timer *)
connect();
}
else if (m_state == ConnectedState) {
if (m_apiVersion == API_DERO) {
rpcSend(JsonRequest::create(m_sequence, "get_info"));
}
else {
send((m_apiVersion == API_MONERO) ? kGetHeight : kGetInfo);
}
send((m_apiVersion == API_MONERO) ? kGetHeight : kGetInfo);
}
}
@@ -330,26 +327,27 @@ void xmrig::DaemonClient::onResolved(const DnsRecords &records, int status, cons
}
delete m_ZMQSocket;
const auto &record = records.get();
m_ip = record.ip();
auto 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_t* s = new uv_tcp_t;
s->data = m_storage.ptr(m_key);
uv_tcp_init(uv_default_loop(), m_ZMQSocket);
uv_tcp_nodelay(m_ZMQSocket, 1);
uv_tcp_init(uv_default_loop(), s);
uv_tcp_nodelay(s, 1);
# ifndef WIN32
uv_tcp_keepalive(m_ZMQSocket, 1, 60);
uv_tcp_keepalive(s, 1, 60);
# endif
uv_tcp_connect(req, m_ZMQSocket, record.addr(m_pool.zmq_port()), onZMQConnect);
if (m_pool.zmq_port() > 0) {
delete m_ZMQSocket;
m_ZMQSocket = s;
uv_tcp_connect(req, s, record.addr(m_pool.zmq_port()), onZMQConnect);
}
}
@@ -396,7 +394,7 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value &params, int *code)
);
# endif
m_blockhashingblob = Json::getString(params, "blockhashing_blob");
m_blockhashingblob = Json::getString(params, kBlockhashingBlob);
if (m_blocktemplate.hasMinerSignature()) {
if (m_pool.spendSecretKey().isEmpty()) {
@@ -452,11 +450,6 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value &params, int *code)
# endif
}
if (m_apiVersion == API_DERO) {
const uint64_t offset = Json::getUint64(params, "reserved_offset");
Cvt::toHex(m_blockhashingblob.data() + offset * 2, kBlobReserveSize * 2, Cvt::randomBytes(kBlobReserveSize).data(), kBlobReserveSize);
}
if (m_coin.isValid()) {
job.setAlgorithm(m_coin.algorithm(m_blocktemplate.majorVersion()));
}
@@ -477,13 +470,6 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value &params, int *code)
m_blocktemplateStr = std::move(blocktemplate);
m_prevHash = Json::getString(params, "prev_hash");
if (m_apiVersion == API_DERO) {
// Truncate to 32 bytes to have the same data as in get_info RPC
if (m_prevHash.size() > 64) {
m_prevHash.data()[64] = '\0';
}
}
if (m_state == ConnectingState) {
setState(ConnectedState);
}
@@ -527,13 +513,6 @@ bool xmrig::DaemonClient::parseResponse(int64_t id, const rapidjson::Value &resu
const char* error_msg = nullptr;
if ((m_apiVersion == API_DERO) && result.HasMember("status")) {
error_msg = result["status"].GetString();
if (!error_msg || (strlen(error_msg) == 0) || (strcmp(error_msg, "OK") == 0)) {
error_msg = nullptr;
}
}
if (handleSubmitResponse(id, error_msg)) {
if (error_msg || (m_pool.zmq_port() < 0)) {
getBlockTemplate();
@@ -554,12 +533,7 @@ int64_t xmrig::DaemonClient::getBlockTemplate()
Value params(kObjectType);
params.AddMember("wallet_address", m_user.toJSON(), allocator);
if (m_apiVersion == API_DERO) {
params.AddMember("reserve_size", static_cast<uint64_t>(kBlobReserveSize), allocator);
}
else {
params.AddMember("extra_nonce", Cvt::toHex(Cvt::randomBytes(kBlobReserveSize)).toJSON(doc), allocator);
}
params.AddMember("extra_nonce", Cvt::toHex(Cvt::randomBytes(kBlobReserveSize)).toJSON(doc), allocator);
JsonRequest::create(doc, m_sequence, "getblocktemplate", params);
@@ -885,10 +859,14 @@ void xmrig::DaemonClient::ZMQParse()
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());
msg.push_back('\0');
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() - 1, msg.data());
# endif
getBlockTemplate();
// Clear previous hash and check daemon height to guarantee that xmrig will call get_block_template RPC later
// We can't call get_block_template directly because daemon is not ready yet
m_prevHash = nullptr;
send(kGetHeight);
}

View File

@@ -39,6 +39,12 @@ using uv_handle_t = struct uv_handle_s;
using uv_stream_t = struct uv_stream_s;
using uv_tcp_t = struct uv_tcp_s;
#ifdef XMRIG_FEATURE_TLS
using BIO = struct bio_st;
using SSL = struct ssl_st;
using SSL_CTX = struct ssl_ctx_st;
#endif
namespace xmrig {
@@ -88,7 +94,6 @@ private:
enum {
API_CRYPTONOTE_DEFAULT,
API_MONERO,
API_DERO,
} m_apiVersion = API_MONERO;
BlockTemplate m_blocktemplate;

View File

@@ -34,6 +34,16 @@
#include "base/kernel/interfaces/IClientListener.h"
#include "net/JobResult.h"
#ifdef XMRIG_ALGO_GHOSTRIDER
#include <cmath>
extern "C" {
#include "crypto/ghostrider/sph_sha2.h"
}
#include "base/tools/Cvt.h"
#endif
xmrig::EthStratumClient::EthStratumClient(int id, const char *agent, IClientListener *listener) :
@@ -63,32 +73,56 @@ int64_t xmrig::EthStratumClient::submit(const JobResult& result)
auto& allocator = doc.GetAllocator();
Value params(kArrayType);
params.PushBack(m_pool.user().toJSON(), allocator);
params.PushBack(m_user.toJSON(), allocator);
params.PushBack(result.jobId.toJSON(), allocator);
std::stringstream s;
s << "0x" << std::hex << std::setw(16) << std::setfill('0') << result.nonce;
params.PushBack(Value(s.str().c_str(), allocator), allocator);
# ifdef XMRIG_ALGO_GHOSTRIDER
if (m_pool.algorithm().id() == Algorithm::GHOSTRIDER_RTM) {
params.PushBack(Value("00000000000000000000000000000000", static_cast<uint32_t>(m_extraNonce2Size * 2)), allocator);
params.PushBack(Value(m_ntime.data(), allocator), allocator);
s.str(std::string());
s << "0x";
for (size_t i = 0; i < 32; ++i) {
const uint32_t k = result.headerHash()[i];
s << std::hex << std::setw(2) << std::setfill('0') << k;
std::stringstream s;
s << std::hex << std::setw(8) << std::setfill('0') << result.nonce;
params.PushBack(Value(s.str().c_str(), allocator), allocator);
}
params.PushBack(Value(s.str().c_str(), allocator), allocator);
else
# endif
{
std::stringstream s;
s << "0x" << std::hex << std::setw(16) << std::setfill('0') << result.nonce;
params.PushBack(Value(s.str().c_str(), allocator), allocator);
s.str(std::string());
s << "0x";
for (size_t i = 0; i < 32; ++i) {
const uint32_t k = result.mixHash()[i];
s << std::hex << std::setw(2) << std::setfill('0') << k;
s.str(std::string());
s << "0x";
for (size_t i = 0; i < 32; ++i) {
const uint32_t k = result.headerHash()[i];
s << std::hex << std::setw(2) << std::setfill('0') << k;
}
params.PushBack(Value(s.str().c_str(), allocator), allocator);
s.str(std::string());
s << "0x";
for (size_t i = 0; i < 32; ++i) {
const uint32_t k = result.mixHash()[i];
s << std::hex << std::setw(2) << std::setfill('0') << k;
}
params.PushBack(Value(s.str().c_str(), allocator), allocator);
}
params.PushBack(Value(s.str().c_str(), allocator), allocator);
JsonRequest::create(doc, m_sequence, "mining.submit", params);
uint64_t actual_diff = ethash_swap_u64(*((uint64_t*)result.result()));
uint64_t actual_diff;
# ifdef XMRIG_ALGO_GHOSTRIDER
if (result.algorithm == Algorithm::GHOSTRIDER_RTM) {
actual_diff = reinterpret_cast<const uint64_t*>(result.result())[3];
}
else
# endif
{
actual_diff = ethash_swap_u64(*((uint64_t*)result.result()));
}
actual_diff = actual_diff ? (uint64_t(-1) / actual_diff) : 0;
# ifdef XMRIG_PROXY_PROJECT
@@ -161,6 +195,34 @@ void xmrig::EthStratumClient::parseNotification(const char *method, const rapidj
setExtraNonce(arr[0]);
}
# ifdef XMRIG_ALGO_GHOSTRIDER
if (strcmp(method, "mining.set_difficulty") == 0) {
if (!params.IsArray()) {
LOG_ERR("%s " RED("invalid mining.set_difficulty notification: params is not an array"), tag());
return;
}
if (m_pool.algorithm().id() != Algorithm::GHOSTRIDER_RTM) {
return;
}
auto arr = params.GetArray();
if (arr.Empty()) {
LOG_ERR("%s " RED("invalid mining.set_difficulty notification: params array is empty"), tag());
return;
}
if (!arr[0].IsDouble() && !arr[0].IsUint64()) {
LOG_ERR("%s " RED("invalid mining.set_difficulty notification: difficulty is not a number"), tag());
return;
}
const double diff = arr[0].IsDouble() ? arr[0].GetDouble() : arr[0].GetUint64();
m_nextDifficulty = static_cast<uint64_t>(ceil(diff * 65536.0));
}
# endif
if (strcmp(method, "mining.notify") == 0) {
if (!params.IsArray()) {
LOG_ERR("%s " RED("invalid mining.notify notification: params is not an array"), tag());
@@ -169,44 +231,152 @@ void xmrig::EthStratumClient::parseNotification(const char *method, const rapidj
auto arr = params.GetArray();
if (arr.Size() < 6) {
auto algo = m_pool.algorithm();
if (!algo.isValid()) {
algo = m_pool.coin().algorithm();
}
const size_t min_arr_size = (algo.id() == Algorithm::GHOSTRIDER_RTM) ? 8 : 6;
if (arr.Size() < min_arr_size) {
LOG_ERR("%s " RED("invalid mining.notify notification: params array has wrong size"), tag());
return;
}
if (!arr[0].IsString()) {
LOG_ERR("%s " RED("invalid mining.notify notification: invalid job id"), tag());
return;
}
Job job;
job.setId(arr[0].GetString());
auto algo = m_pool.algorithm();
if (!algo.isValid()) {
algo = m_pool.coin().algorithm();
}
job.setAlgorithm(algo);
job.setExtraNonce(m_extraNonce.second);
std::stringstream s;
// header hash (32 bytes)
s << arr[1].GetString();
# ifdef XMRIG_ALGO_GHOSTRIDER
if (algo.id() == Algorithm::GHOSTRIDER_RTM) {
// Raptoreum uses Bitcoin's Stratum protocol
// https://en.bitcoinwiki.org/wiki/Stratum_mining_protocol#mining.notify
// nonce template (8 bytes)
for (uint64_t i = 0, k = m_extraNonce.first; i < sizeof(m_extraNonce.first); ++i, k >>= 8) {
s << std::hex << std::setw(2) << std::setfill('0') << (k & 0xFF);
if (!arr[1].IsString() || !arr[2].IsString() || !arr[3].IsString() || !arr[4].IsArray() || !arr[5].IsString() || !arr[6].IsString() || !arr[7].IsString()) {
LOG_ERR("%s " RED("invalid mining.notify notification: invalid param array"), tag());
return;
}
// Version
s << arr[5].GetString();
// Previous block hash
s << arr[1].GetString();
// Merkle tree root
std::string blob = arr[2].GetString();
blob += m_extraNonce.second;
blob.append(m_extraNonce2Size * 2, '0');
blob += arr[3].GetString();
uint8_t merkle_root[64];
Buffer buf = Cvt::fromHex(blob.c_str(), blob.length());
// Get height from coinbase
{
uint8_t* p = buf.data() + 32;
uint8_t* m = p + 128;
while ((p < m) && (*p != 0xff)) ++p;
while ((p < m) && (*p == 0xff)) ++p;
if ((p < m) && (*(p - 1) == 0xff) && (*(p - 2) == 0xff)) {
uint32_t height = *reinterpret_cast<uint16_t*>(p + 2);
switch (*(p + 1)) {
case 4:
height += *reinterpret_cast<uint16_t*>(p + 4) * 0x10000UL;
break;
case 3:
height += *(p + 4) * 0x10000UL;
break;
}
job.setHeight(height);
}
else {
job.setHeight(0);
}
}
sha256d(merkle_root, buf.data(), static_cast<int>(buf.size()));
auto merkle_branches = arr[4].GetArray();
for (int i = 0, n = merkle_branches.Size(); i < n; ++i) {
auto& b = merkle_branches[i];
buf = b.IsString() ? Cvt::fromHex(b.GetString(), b.GetStringLength()) : Buffer();
if (buf.size() != 32) {
LOG_ERR("%s " RED("invalid mining.notify notification: param 4 is invalid"), tag());
return;
}
memcpy(merkle_root + 32, buf.data(), 32);
sha256d(merkle_root, merkle_root, 64);
}
s << Cvt::toHex(merkle_root, 32);
// ntime
m_ntime = arr[7].GetString();
s << m_ntime;
// nbits
s << arr[6].GetString();
blob = s.str();
if (blob.size() != 76 * 2) {
LOG_ERR("%s " RED("invalid mining.notify notification: invalid blob size"), tag());
return;
}
// zeros up to 80 bytes
blob.resize(80 * 2, '0');
// Invert byte order (no idea why, but it's done in Bitcoin's Stratum)
buf = Cvt::fromHex(blob.c_str(), blob.length());
for (size_t i = 0; i < 80; i += sizeof(uint32_t)) {
uint32_t& k = *reinterpret_cast<uint32_t*>(buf.data() + i);
if ((i < 36) || (i >= 68)) {
k = ethash_swap_u32(k);
}
}
blob = Cvt::toHex(buf.data(), buf.size());
job.setBlob(blob.c_str());
job.setDiff(m_nextDifficulty);
}
else
# endif
{
// header hash (32 bytes)
s << arr[1].GetString();
std::string blob = s.str();
// nonce template (8 bytes)
for (uint64_t i = 0, k = m_extraNonce.first; i < sizeof(m_extraNonce.first); ++i, k >>= 8) {
s << std::hex << std::setw(2) << std::setfill('0') << (k & 0xFF);
}
// zeros up to 76 bytes
blob.resize(76 * 2, '0');
job.setBlob(blob.c_str());
std::string blob = s.str();
std::string target_str = arr[3].GetString();
target_str.resize(16, '0');
const uint64_t target = strtoull(target_str.c_str(), nullptr, 16);
job.setDiff(Job::toDiff(target));
// zeros up to 76 bytes
blob.resize(76 * 2, '0');
job.setBlob(blob.c_str());
job.setHeight(arr[5].GetUint64());
std::string target_str = arr[3].GetString();
target_str.resize(16, '0');
const uint64_t target = strtoull(target_str.c_str(), nullptr, 16);
job.setDiff(Job::toDiff(target));
job.setHeight(arr[5].GetUint64());
}
bool ok = true;
m_listener->onVerifyAlgorithm(this, algo, &ok);
@@ -301,8 +471,8 @@ void xmrig::EthStratumClient::authorize()
auto &allocator = doc.GetAllocator();
Value params(kArrayType);
params.PushBack(m_pool.user().toJSON(), allocator);
params.PushBack(m_pool.password().toJSON(), allocator);
params.PushBack(m_user.toJSON(), allocator);
params.PushBack(m_password.toJSON(), allocator);
JsonRequest::create(doc, m_sequence, "mining.authorize", params);
@@ -356,11 +526,19 @@ void xmrig::EthStratumClient::onSubscribeResponse(const rapidjson::Value &result
throw std::runtime_error("invalid mining.subscribe response: result is not an array");
}
if (result.GetArray().Size() <= 1) {
auto arr = result.GetArray();
if (arr.Size() <= 1) {
throw std::runtime_error("invalid mining.subscribe response: result array is too short");
}
setExtraNonce(result.GetArray()[1]);
setExtraNonce(arr[1]);
# ifdef XMRIG_ALGO_GHOSTRIDER
if ((arr.Size() > 2) && (arr[2].IsUint())) {
m_extraNonce2Size = arr[2].GetUint();
}
# endif
if (m_pool.isNicehash()) {
using namespace rapidjson;

View File

@@ -47,6 +47,10 @@ protected:
void setExtraNonce(const rapidjson::Value &nonce);
# ifdef XMRIG_ALGO_GHOSTRIDER
inline void setExtraNonce2Size(uint64_t size) { m_extraNonce2Size = size; }
# endif
private:
static const char *errorMessage(const rapidjson::Value &error);
@@ -57,6 +61,12 @@ private:
bool m_authorized = false;
std::pair<uint64_t, String> m_extraNonce{};
# ifdef XMRIG_ALGO_GHOSTRIDER
uint64_t m_extraNonce2Size = 0;
uint64_t m_nextDifficulty = 0;
String m_ntime;
# endif
};

View File

@@ -30,6 +30,7 @@
#include "base/net/stratum/Job.h"
#include "base/tools/Alignment.h"
#include "base/tools/Buffer.h"
#include "base/tools/Cvt.h"
#include "base/tools/cryptonote/BlockTemplate.h"
@@ -47,7 +48,7 @@ xmrig::Job::Job(bool nicehash, const Algorithm &algorithm, const String &clientI
bool xmrig::Job::isEqual(const Job &other) const
{
return m_id == other.m_id && m_clientId == other.m_clientId && memcmp(m_blob, other.m_blob, sizeof(m_blob)) == 0;
return m_id == other.m_id && m_clientId == other.m_clientId && memcmp(m_blob, other.m_blob, sizeof(m_blob)) == 0 && m_target == other.m_target;
}
@@ -73,7 +74,7 @@ bool xmrig::Job::setBlob(const char *blob)
return false;
}
if (*nonce() != 0 && !m_nicehash) {
if (readUnaligned(nonce()) != 0 && !m_nicehash) {
m_nicehash = true;
}
@@ -163,6 +164,14 @@ void xmrig::Job::setSigKey(const char *sig_key)
}
int32_t xmrig::Job::nonceOffset() const
{
auto f = algorithm().family();
if (f == Algorithm::KAWPOW) return 32;
if (f == Algorithm::GHOSTRIDER) return 76;
return 39;
}
uint32_t xmrig::Job::getNumTransactions() const
{
if (!(m_algorithm.isCN() || m_algorithm.family() == Algorithm::RANDOM_X)) {

View File

@@ -76,7 +76,7 @@ public:
inline const String &poolWallet() const { return m_poolWallet; }
inline const uint32_t *nonce() const { return reinterpret_cast<const uint32_t*>(m_blob + nonceOffset()); }
inline const uint8_t *blob() const { return m_blob; }
inline int32_t nonceOffset() const { return (algorithm().family() == Algorithm::KAWPOW) ? 32 : 39; }
int32_t nonceOffset() const;
inline size_t nonceSize() const { return (algorithm().family() == Algorithm::KAWPOW) ? 8 : 4; }
inline size_t size() const { return m_size; }
inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + nonceOffset()); }

View File

@@ -31,7 +31,7 @@
#include "base/kernel/Platform.h"
#include "base/net/stratum/Client.h"
#ifdef XMRIG_ALGO_KAWPOW
#if defined XMRIG_ALGO_KAWPOW || defined XMRIG_ALGO_GHOSTRIDER
# include "base/net/stratum/AutoClient.h"
# include "base/net/stratum/EthStratumClient.h"
#endif
@@ -218,8 +218,9 @@ xmrig::IClient *xmrig::Pool::createClient(int id, IClientListener *listener) con
IClient *client = nullptr;
if (m_mode == MODE_POOL) {
# ifdef XMRIG_ALGO_KAWPOW
if ((m_algorithm.family() == Algorithm::KAWPOW) || (m_coin == Coin::RAVEN)) {
# if defined XMRIG_ALGO_KAWPOW || defined XMRIG_ALGO_GHOSTRIDER
const uint32_t f = m_algorithm.family();
if ((f == Algorithm::KAWPOW) || (f == Algorithm::GHOSTRIDER) || (m_coin == Coin::RAVEN)) {
client = new EthStratumClient(id, Platform::userAgent(), listener);
}
else
@@ -236,7 +237,7 @@ xmrig::IClient *xmrig::Pool::createClient(int id, IClientListener *listener) con
client = new SelfSelectClient(id, Platform::userAgent(), listener, m_submitToOrigin);
}
# endif
# ifdef XMRIG_ALGO_KAWPOW
# if defined XMRIG_ALGO_KAWPOW || defined XMRIG_ALGO_GHOSTRIDER
else if (m_mode == MODE_AUTO_ETH) {
client = new AutoClient(id, Platform::userAgent(), listener);
}

View File

@@ -111,6 +111,7 @@ public:
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 setUrl(const char *url) { m_url = Url(url); }
inline void setPassword(const String &password) { m_password = password; }
inline void setProxy(const ProxyUrl &proxy) { m_proxy = proxy; }
inline void setRigId(const String &rigId) { m_rigId = rigId; }

View File

@@ -171,7 +171,7 @@ uint32_t xmrig::Pools::benchSize() const
return m_benchmark ? m_benchmark->size() : 0;
# else
return 0;
# endif
# endif
}

View File

@@ -72,7 +72,14 @@ int64_t xmrig::SelfSelectClient::submit(const JobResult &result)
submitOriginDaemon(result);
}
return m_client->submit(result);
uint64_t submit_result = m_client->submit(result);
if (m_submitToOrigin) {
// Ensure that the latest block template is available after block submission
getBlockTemplate();
}
return submit_result;
}
@@ -257,7 +264,7 @@ void xmrig::SelfSelectClient::submitOriginDaemon(const JobResult& result)
if (result.diff == 0 || m_blockDiff == 0) {
return;
}
if (result.actualDiff() < m_blockDiff) {
m_originNotSubmitted++;
LOG_DEBUG("%s " RED_BOLD("not submitted to origin daemon, difficulty too low") " (%" PRId64 "/%" PRId64 ") "
@@ -280,14 +287,11 @@ void xmrig::SelfSelectClient::submitOriginDaemon(const JobResult& result)
FetchRequest req(HTTP_POST, pool().daemon().host(), pool().daemon().port(), "/json_rpc", doc, pool().daemon().isTLS(), isQuiet());
fetch(tag(), std::move(req), m_httpListener);
m_originSubmitted++;
LOG_INFO("%s " GREEN_BOLD("submitted to origin daemon") " (%" PRId64 "/%" PRId64 ") "
LOG_INFO("%s " GREEN_BOLD("submitted to origin daemon") " (%" PRId64 "/%" PRId64 ") "
" diff " WHITE("%" PRIu64) " vs. " WHITE("%" PRIu64),
Tags::origin(), m_originSubmitted, m_originNotSubmitted, m_blockDiff, result.actualDiff(), result.diff);
// Ensure that the latest block template is available after block submission
getBlockTemplate();
}
void xmrig::SelfSelectClient::onHttpData(const HttpData &data)

View File

@@ -0,0 +1,53 @@
/* XMRig
* Copyright (c) 2018-2022 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2022 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_ALIGNMENT_H
#define XMRIG_ALIGNMENT_H
#include <type_traits>
#include <cstring>
namespace xmrig {
template<typename T>
inline T readUnaligned(const T* ptr)
{
static_assert(std::is_trivially_copyable<T>::value, "T must be trivially copyable");
T result;
memcpy(&result, ptr, sizeof(T));
return result;
}
template<typename T>
inline void writeUnaligned(T* ptr, T data)
{
static_assert(std::is_trivially_copyable<T>::value, "T must be trivially copyable");
memcpy(ptr, &data, sizeof(T));
}
} /* namespace xmrig */
#endif /* XMRIG_ALIGNMENT_H */

44
src/base/tools/Chrono.cpp Normal file
View File

@@ -0,0 +1,44 @@
/* 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/>.
*/
#include "Chrono.h"
#ifdef XMRIG_OS_WIN
# include <Windows.h>
#endif
namespace xmrig {
double Chrono::highResolutionMSecs()
{
# ifdef XMRIG_OS_WIN
LARGE_INTEGER f, t;
QueryPerformanceFrequency(&f);
QueryPerformanceCounter(&t);
return static_cast<double>(t.QuadPart) * 1e3 / f.QuadPart;
# else
using namespace std::chrono;
return static_cast<uint64_t>(duration_cast<nanoseconds>(high_resolution_clock::now().time_since_epoch()).count()) / 1e6;
# endif
}
} /* namespace xmrig */

View File

@@ -29,12 +29,7 @@ namespace xmrig {
class Chrono
{
public:
static inline uint64_t highResolutionMSecs()
{
using namespace std::chrono;
return static_cast<uint64_t>(time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count());
}
static double highResolutionMSecs();
static inline uint64_t steadyMSecs()

View File

@@ -23,10 +23,12 @@
#include <stdlib.h>
#define bswap_64(x) _byteswap_uint64(x)
#define bswap_32(x) _byteswap_ulong(x)
#elif defined __GNUC__
#define bswap_64(x) __builtin_bswap64(x)
#define bswap_32(x) __builtin_bswap32(x)
#else

View File

@@ -228,14 +228,19 @@ bool xmrig::BlockTemplate::parse(bool hashes)
ar(m_amount);
ar(m_outputType);
// output type must be txout_to_key (2)
if (m_outputType != 2) {
// output type must be txout_to_key (2) or txout_to_tagged_key (3)
if ((m_outputType != 2) && (m_outputType != 3)) {
return false;
}
setOffset(EPH_PUBLIC_KEY_OFFSET, ar.index());
ar(m_ephPublicKey, kKeySize);
if (m_outputType == 3) {
ar(m_viewTag);
}
ar(m_extraSize);
setOffset(TX_EXTRA_OFFSET, ar.index());
@@ -244,7 +249,9 @@ bool xmrig::BlockTemplate::parse(bool hashes)
ar.skip(m_extraSize);
while (ar_extra.index() < m_extraSize) {
uint64_t extra_tag = 0;
uint64_t extra_tag = 0;
uint64_t size = 0;
ar_extra(extra_tag);
switch (extra_tag) {
@@ -254,12 +261,15 @@ bool xmrig::BlockTemplate::parse(bool hashes)
break;
case 0x02: // TX_EXTRA_NONCE
{
uint64_t size = 0;
ar_extra(size);
setOffset(TX_EXTRA_NONCE_OFFSET, offset(TX_EXTRA_OFFSET) + ar_extra.index());
ar_extra(m_txExtraNonce, size);
}
ar_extra(size);
setOffset(TX_EXTRA_NONCE_OFFSET, offset(TX_EXTRA_OFFSET) + ar_extra.index());
ar_extra(m_txExtraNonce, size);
break;
case 0x03: // TX_EXTRA_MERGE_MINING_TAG
ar_extra(size);
setOffset(TX_EXTRA_MERGE_MINING_TAG_OFFSET, offset(TX_EXTRA_OFFSET) + ar_extra.index());
ar_extra(m_txMergeMiningTag, size + kKeySize);
break;
default:

View File

@@ -54,6 +54,7 @@ public:
TX_EXTRA_OFFSET,
TX_PUBKEY_OFFSET,
TX_EXTRA_NONCE_OFFSET,
TX_EXTRA_MERGE_MINING_TAG_OFFSET,
OFFSET_COUNT
};
@@ -86,6 +87,7 @@ public:
inline uint64_t outputType() const { return m_outputType; }
inline const Span &ephPublicKey() const { return m_ephPublicKey; }
inline const Span &txExtraNonce() const { return m_txExtraNonce; }
inline const Span &txMergeMiningTag() const { return m_txMergeMiningTag; }
// Transaction hashes
inline uint64_t numHashes() const { return m_numHashes; }
@@ -138,9 +140,10 @@ private:
uint64_t m_amount = 0;
uint8_t m_outputType = 0;
Span m_ephPublicKey;
uint8_t m_viewTag = 0;
uint64_t m_extraSize = 0;
Span m_txExtraNonce;
Span m_txMergeMiningTag = 0;
uint64_t m_numHashes = 0;
Buffer m_hashes;
Buffer m_minerTxMerkleTreeBranch;

View File

@@ -217,12 +217,6 @@ const xmrig::WalletAddress::TagInfo &xmrig::WalletAddress::tagInfo(uint64_t tag)
{ 0x1742ca, { Coin::ARQMA, STAGENET, INTEGRATED, 39994, 39995 } },
{ 0x1d84ca, { Coin::ARQMA, STAGENET, SUBADDRESS, 39994, 39995 } },
{ 0xc8ed8, { Coin::DERO, MAINNET, PUBLIC, 20206, 0 } },
{ 0xa0ed8, { Coin::DERO, MAINNET, INTEGRATED, 20206, 0 } },
{ 0x6cf58, { Coin::DERO, TESTNET, PUBLIC, 30306, 0 } },
{ 0x44f58, { Coin::DERO, TESTNET, INTEGRATED, 30306, 0 } },
{ 0x1032, { Coin::WOWNERO, MAINNET, PUBLIC, 34568, 34569 } },
{ 0x1a9a, { Coin::WOWNERO, MAINNET, INTEGRATED, 34568, 34569 } },
{ 0x2fb0, { Coin::WOWNERO, MAINNET, SUBADDRESS, 34568, 34569 } },

View File

@@ -1,21 +1,21 @@
// Copyright (c) 2014-2020, The Monero Project
//
//
// All rights reserved.
//
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include <stdint.h>

View File

@@ -1,21 +1,21 @@
// Copyright (c) 2014-2020, The Monero Project
//
//
// All rights reserved.
//
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include <assert.h>

View File

@@ -1,21 +1,21 @@
// Copyright (c) 2014-2020, The Monero Project
//
//
// All rights reserved.
//
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
@@ -25,7 +25,7 @@
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#pragma once

View File

@@ -41,10 +41,6 @@
xmrig::ExtraNonceSplitter* xmrig::ExtraNonceSplitter::Create(Controller* controller)
{
for (const Pool& pool : controller->config()->pools().data()) {
if ((pool.algorithm() == Algorithm::ASTROBWT_DERO) || (pool.coin() == Coin::DERO)) {
LOG_ERR("extra_nonce mode is incompatible with Dero mining");
return nullptr;
}
if (pool.mode() != Pool::MODE_DAEMON) {
LOG_ERR("extra_nonce mode can only be used when mining to daemon");
return nullptr;