Compare commits
82 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
02b2b87bb6 | ||
|
c8a9dba8fd | ||
|
9a77d39a3f | ||
|
28a1d0fe1e | ||
|
0243789c04 | ||
|
45dd58f808 | ||
|
1b4abe1e98 | ||
|
9f778742a6 | ||
|
015f8aeed4 | ||
|
9e6311a7e0 | ||
|
0af9d2e75b | ||
|
6e2a84a46c | ||
|
6bb8913066 | ||
|
cf104ebdc5 | ||
|
ecba750442 | ||
|
3967badc55 | ||
|
3f3f9b0661 | ||
|
e3fc78a66c | ||
|
e6d833c227 | ||
|
ebe299902c | ||
|
bc63b63a2a | ||
|
e739e7d704 | ||
|
1bae083587 | ||
|
88959bd703 | ||
|
93e689d601 | ||
|
a136790bee | ||
|
29f2dd4b9e | ||
|
3003c067d3 | ||
|
89bc6418b1 | ||
|
8458b4ee39 | ||
|
7bfb801ce2 | ||
|
4567499905 | ||
|
9b63955b09 | ||
|
0414511de0 | ||
|
b61dad128c | ||
|
80ae339343 | ||
|
4d87555398 | ||
|
bef82c5de6 | ||
|
b069ad5dd1 | ||
|
f6a0646271 | ||
|
b5f1a1feae | ||
|
1ce059da1c | ||
|
2929451ee1 | ||
|
94fecb5e92 | ||
|
3bfa5ea038 | ||
|
ff82ca57f2 | ||
|
7f7b1fb073 | ||
|
d443dd86f1 | ||
|
3ac8f6b23a | ||
|
9b1f020a8b | ||
|
8bf88a4e74 | ||
|
08a2c143f5 | ||
|
4eb9a1aad5 | ||
|
c8c40586a1 | ||
|
29cb416107 | ||
|
465169ff12 | ||
|
df2bcd8192 | ||
|
d89bb56964 | ||
|
87a0864e3b | ||
|
ecf5579f36 | ||
|
d5523d819f | ||
|
dbda2e9ccd | ||
|
8babd7bc0a | ||
|
27ced139a6 | ||
|
b46849e813 | ||
|
a96a6108ff | ||
|
c50c78b700 | ||
|
cd7ab2c79f | ||
|
695fbc013b | ||
|
a403c53543 | ||
|
e26fbc96e9 | ||
|
259c165e60 | ||
|
7897bf02dc | ||
|
05f62c5ccc | ||
|
d82e100e30 | ||
|
5f869a414c | ||
|
7fd6be7d83 | ||
|
ae6c536e98 | ||
|
c66c593123 | ||
|
b3788b2ba3 | ||
|
b7adb34c37 | ||
|
2012ffb231 |
24
CHANGELOG.md
24
CHANGELOG.md
@ -1,3 +1,27 @@
|
||||
# v6.13.1
|
||||
- [#2468](https://github.com/xmrig/xmrig/pull/2468) Fixed regression in previous version: don't send miner signature during regular mining.
|
||||
|
||||
# v6.13.0
|
||||
- [#2445](https://github.com/xmrig/xmrig/pull/2445) Added support for solo mining with miner signatures for the upcoming Wownero fork.
|
||||
|
||||
# v6.12.2
|
||||
- [#2280](https://github.com/xmrig/xmrig/issues/2280) GPU backends are now disabled in benchmark mode.
|
||||
- [#2322](https://github.com/xmrig/xmrig/pull/2322) Improved MSR compatibility with recent Linux kernels and updated `randomx_boost.sh`.
|
||||
- [#2340](https://github.com/xmrig/xmrig/pull/2340) Fixed AES detection on FreeBSD on ARM.
|
||||
- [#2341](https://github.com/xmrig/xmrig/pull/2341) `sse2neon` updated to the latest version.
|
||||
- [#2351](https://github.com/xmrig/xmrig/issues/2351) Fixed help output for `--cpu-priority` and `--cpu-affinity` option.
|
||||
- [#2375](https://github.com/xmrig/xmrig/pull/2375) Fixed macOS CUDA backend default loader name.
|
||||
- [#2378](https://github.com/xmrig/xmrig/pull/2378) Fixed broken light mode mining on x86.
|
||||
- [#2379](https://github.com/xmrig/xmrig/pull/2379) Fixed CL code for KawPow where it assumes everything is AMD.
|
||||
- [#2386](https://github.com/xmrig/xmrig/pull/2386) RandomX: enabled `IMUL_RCP` optimization for light mode mining.
|
||||
- [#2393](https://github.com/xmrig/xmrig/pull/2393) RandomX: added BMI2 version for scratchpad prefetch.
|
||||
- [#2395](https://github.com/xmrig/xmrig/pull/2395) RandomX: rewrote dataset read code.
|
||||
- [#2398](https://github.com/xmrig/xmrig/pull/2398) RandomX: optimized ARMv8 dataset read.
|
||||
- Added `argon2/ninja` alias for `argon2/wrkz` algorithm.
|
||||
|
||||
# v6.12.1
|
||||
- [#2296](https://github.com/xmrig/xmrig/pull/2296) Fixed Zen3 assembly code for `cn/upx2` algorithm.
|
||||
|
||||
# v6.12.0
|
||||
- [#2276](https://github.com/xmrig/xmrig/pull/2276) Added support for Uplexa (`cn/upx2` algorithm).
|
||||
- [#2261](https://github.com/xmrig/xmrig/pull/2261) Show total hashrate if compiled without OpenCL.
|
||||
|
@ -1,3 +1,7 @@
|
||||
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
add_definitions(/DXMRIG_64_BIT)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
set(XMRIG_OS_WIN ON)
|
||||
elseif (APPLE)
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
OPENSSL_VERSION="1.1.1j"
|
||||
OPENSSL_VERSION="1.1.1k"
|
||||
|
||||
mkdir -p deps
|
||||
mkdir -p deps/include
|
||||
@ -17,4 +17,4 @@ make -j$(nproc || sysctl -n hw.ncpu || sysctl -n hw.logicalcpu)
|
||||
cp -fr include ../../deps
|
||||
cp libcrypto.a ../../deps/lib
|
||||
cp libssl.a ../../deps/lib
|
||||
cd ..
|
||||
cd ..
|
||||
|
@ -1,28 +1,34 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh -e
|
||||
|
||||
modprobe msr
|
||||
MSR_FILE=/sys/module/msr/parameters/allow_writes
|
||||
|
||||
if cat /proc/cpuinfo | grep "AMD Ryzen" > /dev/null;
|
||||
if test -e "$MSR_FILE"; then
|
||||
echo on > $MSR_FILE
|
||||
else
|
||||
modprobe msr allow_writes=on
|
||||
fi
|
||||
|
||||
if grep -E 'AMD Ryzen|AMD EPYC' /proc/cpuinfo > /dev/null;
|
||||
then
|
||||
if cat /proc/cpuinfo | grep "cpu family[[:space:]]:[[:space:]]25" > /dev/null;
|
||||
if grep "cpu family[[:space:]]:[[:space:]]25" /proc/cpuinfo > /dev/null;
|
||||
then
|
||||
echo "Detected Ryzen (Zen3)"
|
||||
echo "Detected Zen3 CPU"
|
||||
wrmsr -a 0xc0011020 0x4480000000000
|
||||
wrmsr -a 0xc0011021 0x1c000200000040
|
||||
wrmsr -a 0xc0011022 0xc000000401500000
|
||||
wrmsr -a 0xc001102b 0x2000cc14
|
||||
echo "MSR register values for Ryzen (Zen3) applied"
|
||||
echo "MSR register values for Zen3 applied"
|
||||
else
|
||||
echo "Detected Ryzen (Zen1/Zen2)"
|
||||
echo "Detected Zen1/Zen2 CPU"
|
||||
wrmsr -a 0xc0011020 0
|
||||
wrmsr -a 0xc0011021 0x40
|
||||
wrmsr -a 0xc0011022 0x1510000
|
||||
wrmsr -a 0xc001102b 0x2000cc16
|
||||
echo "MSR register values for Ryzen (Zen1/Zen2) applied"
|
||||
echo "MSR register values for Zen1/Zen2 applied"
|
||||
fi
|
||||
elif cat /proc/cpuinfo | grep "Intel" > /dev/null;
|
||||
elif grep "Intel" /proc/cpuinfo > /dev/null;
|
||||
then
|
||||
echo "Detected Intel"
|
||||
echo "Detected Intel CPU"
|
||||
wrmsr -a 0x1a4 0xf
|
||||
echo "MSR register values for Intel applied"
|
||||
else
|
||||
|
@ -85,9 +85,10 @@ public:
|
||||
}
|
||||
|
||||
|
||||
inline int32_t nonceOffset() const { return currentJob().nonceOffset(); }
|
||||
inline size_t nonceSize() const { return currentJob().nonceSize(); }
|
||||
|
||||
private:
|
||||
inline int32_t nonceOffset() const { return currentJob().nonceOffset(); }
|
||||
inline size_t nonceSize() const { return currentJob().nonceSize(); }
|
||||
inline uint64_t nonceMask() const { return m_nonce_mask[index()]; }
|
||||
|
||||
inline void save(const Job &job, uint32_t reserveCount, Nonce::Backend backend)
|
||||
|
@ -274,10 +274,16 @@ void xmrig::CpuWorker<N>::start()
|
||||
|
||||
bool valid = true;
|
||||
|
||||
uint8_t miner_signature_saved[64];
|
||||
uint8_t* miner_signature_ptr = m_job.blob() + m_job.nonceOffset() + m_job.nonceSize();
|
||||
|
||||
# ifdef XMRIG_ALGO_RANDOMX
|
||||
if (job.algorithm().family() == Algorithm::RANDOM_X) {
|
||||
if (first) {
|
||||
first = false;
|
||||
if (job.hasMinerSignature()) {
|
||||
job.generateMinerSignature(m_job.blob(), job.size(), miner_signature_ptr);
|
||||
}
|
||||
randomx_calculate_hash_first(m_vm, tempHash, m_job.blob(), job.size());
|
||||
}
|
||||
|
||||
@ -285,6 +291,10 @@ void xmrig::CpuWorker<N>::start()
|
||||
break;
|
||||
}
|
||||
|
||||
if (job.hasMinerSignature()) {
|
||||
memcpy(miner_signature_saved, miner_signature_ptr, sizeof(miner_signature_saved));
|
||||
job.generateMinerSignature(m_job.blob(), job.size(), miner_signature_ptr);
|
||||
}
|
||||
randomx_calculate_hash_next(m_vm, tempHash, m_job.blob(), job.size(), m_hash);
|
||||
}
|
||||
else
|
||||
@ -319,7 +329,7 @@ void xmrig::CpuWorker<N>::start()
|
||||
else
|
||||
# endif
|
||||
if (value < job.target()) {
|
||||
JobResults::submit(job, current_job_nonces[i], m_hash + (i * 32));
|
||||
JobResults::submit(job, current_job_nonces[i], m_hash + (i * 32), job.hasMinerSignature() ? miner_signature_saved : nullptr);
|
||||
}
|
||||
}
|
||||
m_count += N;
|
||||
|
@ -28,7 +28,15 @@
|
||||
|
||||
#if __ARM_FEATURE_CRYPTO && !defined(__APPLE__)
|
||||
# include <sys/auxv.h>
|
||||
# include <asm/hwcap.h>
|
||||
# ifndef __FreeBSD__
|
||||
# include <asm/hwcap.h>
|
||||
# else
|
||||
# include <stdint.h>
|
||||
# include <machine/armreg.h>
|
||||
# ifndef ID_AA64ISAR0_AES_VAL
|
||||
# define ID_AA64ISAR0_AES_VAL ID_AA64ISAR0_AES
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
@ -62,10 +70,13 @@ xmrig::BasicCpuInfo::BasicCpuInfo() :
|
||||
# endif
|
||||
|
||||
# if __ARM_FEATURE_CRYPTO
|
||||
# if !defined(__APPLE__)
|
||||
m_flags.set(FLAG_AES, getauxval(AT_HWCAP) & HWCAP_AES);
|
||||
# else
|
||||
# if defined(__APPLE__)
|
||||
m_flags.set(FLAG_AES, true);
|
||||
# elif defined(__FreeBSD__)
|
||||
uint64_t isar0 = READ_SPECIALREG(id_aa64isar0_el1);
|
||||
m_flags.set(FLAG_AES, ID_AA64ISAR0_AES_VAL(isar0) >= ID_AA64ISAR0_AES_BASE);
|
||||
# else
|
||||
m_flags.set(FLAG_AES, getauxval(AT_HWCAP) & HWCAP_AES);
|
||||
# endif
|
||||
# endif
|
||||
|
||||
|
@ -48,7 +48,7 @@ enum Version : uint32_t
|
||||
static uv_lib_t cudaLib;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
static String defaultLoader = "/System/Library/Frameworks/OpenCL.framework/OpenCL";
|
||||
static String defaultLoader = "libxmrig-cuda.dylib";
|
||||
#elif defined(_WIN32)
|
||||
static String defaultLoader = "xmrig-cuda.dll";
|
||||
#else
|
||||
|
@ -29,7 +29,11 @@ typedef unsigned long uint64_t;
|
||||
#endif
|
||||
|
||||
#ifndef PLATFORM
|
||||
#ifdef cl_amd_media_ops
|
||||
#define PLATFORM OPENCL_PLATFORM_AMD
|
||||
#else
|
||||
#define PLATFORM OPENCL_PLATFORM_UNKNOWN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define HASHES_PER_GROUP (GROUP_SIZE / PROGPOW_LANES)
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -76,6 +76,12 @@ set(HEADERS_BASE
|
||||
src/base/tools/Handle.h
|
||||
src/base/tools/String.h
|
||||
src/base/tools/Timer.h
|
||||
src/base/tools/cryptonote/BlobReader.h
|
||||
src/base/tools/cryptonote/BlockTemplate.h
|
||||
src/base/tools/cryptonote/Signatures.h
|
||||
src/base/tools/cryptonote/WalletAddress.h
|
||||
src/base/tools/cryptonote/crypto-ops.h
|
||||
src/base/tools/cryptonote/umul128.h
|
||||
)
|
||||
|
||||
set(SOURCES_BASE
|
||||
@ -126,6 +132,11 @@ set(SOURCES_BASE
|
||||
src/base/tools/Cvt.cpp
|
||||
src/base/tools/String.cpp
|
||||
src/base/tools/Timer.cpp
|
||||
src/base/tools/cryptonote/BlockTemplate.cpp
|
||||
src/base/tools/cryptonote/Signatures.cpp
|
||||
src/base/tools/cryptonote/WalletAddress.cpp
|
||||
src/base/tools/cryptonote/crypto-ops.c
|
||||
src/base/tools/cryptonote/crypto-ops-data.c
|
||||
)
|
||||
|
||||
|
||||
|
@ -117,6 +117,7 @@ static AlgoName const algorithm_names[] = {
|
||||
{ "chukwa", nullptr, Algorithm::AR2_CHUKWA },
|
||||
{ "argon2/chukwav2", nullptr, Algorithm::AR2_CHUKWA_V2 },
|
||||
{ "chukwav2", nullptr, Algorithm::AR2_CHUKWA_V2 },
|
||||
{ "argon2/ninja", nullptr, Algorithm::AR2_WRKZ },
|
||||
{ "argon2/wrkz", nullptr, Algorithm::AR2_WRKZ },
|
||||
# endif
|
||||
# ifdef XMRIG_ALGO_ASTROBWT
|
||||
|
@ -56,7 +56,8 @@ static CoinName const coin_names[] = {
|
||||
{ "ravencoin", Coin::RAVEN },
|
||||
{ "raven", Coin::RAVEN },
|
||||
{ "rvn", Coin::RAVEN },
|
||||
{ "conceal", Coin::CONCEAL }
|
||||
{ "conceal", Coin::CONCEAL },
|
||||
{ "wownero", Coin::WOWNERO }
|
||||
};
|
||||
|
||||
|
||||
@ -85,6 +86,9 @@ xmrig::Algorithm::Id xmrig::Coin::algorithm(uint8_t blobVersion) const
|
||||
case CONCEAL:
|
||||
return Algorithm::CN_CCX;
|
||||
|
||||
case WOWNERO:
|
||||
return Algorithm::RX_WOW;
|
||||
|
||||
case INVALID:
|
||||
break;
|
||||
}
|
||||
|
@ -44,7 +44,8 @@ public:
|
||||
DERO,
|
||||
KEVA,
|
||||
RAVEN,
|
||||
CONCEAL
|
||||
CONCEAL,
|
||||
WOWNERO
|
||||
};
|
||||
|
||||
|
||||
|
@ -181,6 +181,9 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
|
||||
case IConfig::PasswordKey: /* --pass */
|
||||
return add(doc, Pools::kPools, Pool::kPass, arg);
|
||||
|
||||
case IConfig::SpendSecretKey: /* --spend-secret-key */
|
||||
return add(doc, Pools::kPools, Pool::kSpendSecretKey, arg);
|
||||
|
||||
case IConfig::RigIdKey: /* --rig-id */
|
||||
return add(doc, Pools::kPools, Pool::kRigId, arg);
|
||||
|
||||
|
@ -84,6 +84,7 @@ public:
|
||||
SubmitToOriginKey = 1052,
|
||||
DnsIPv6Key = 1053,
|
||||
DnsTtlKey = 1054,
|
||||
SpendSecretKey = 1055,
|
||||
|
||||
// xmrig common
|
||||
CPUPriorityKey = 1021,
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "base/net/tools/NetBuffer.h"
|
||||
#include "base/tools/Chrono.h"
|
||||
#include "base/tools/Cvt.h"
|
||||
#include "base/tools/cryptonote/BlobReader.h"
|
||||
#include "net/JobResult.h"
|
||||
|
||||
|
||||
@ -83,7 +84,8 @@ static const char *states[] = {
|
||||
xmrig::Client::Client(int id, const char *agent, IClientListener *listener) :
|
||||
BaseClient(id, listener),
|
||||
m_agent(agent),
|
||||
m_sendBuf(1024)
|
||||
m_sendBuf(1024),
|
||||
m_tempBuf(256)
|
||||
{
|
||||
m_reader.setListener(this);
|
||||
m_key = m_storage.add(this);
|
||||
@ -198,11 +200,16 @@ int64_t xmrig::Client::submit(const JobResult &result)
|
||||
const char *nonce = result.nonce;
|
||||
const char *data = result.result;
|
||||
# else
|
||||
char *nonce = m_sendBuf.data();
|
||||
char *data = m_sendBuf.data() + 16;
|
||||
char *nonce = m_tempBuf.data();
|
||||
char *data = m_tempBuf.data() + 16;
|
||||
char *signature = m_tempBuf.data() + 88;
|
||||
|
||||
Cvt::toHex(nonce, sizeof(uint32_t) * 2 + 1, reinterpret_cast<const uint8_t *>(&result.nonce), sizeof(uint32_t));
|
||||
Cvt::toHex(data, 65, result.result(), 32);
|
||||
|
||||
if (result.minerSignature()) {
|
||||
Cvt::toHex(signature, 129, result.minerSignature(), 64);
|
||||
}
|
||||
# endif
|
||||
|
||||
Document doc(kObjectType);
|
||||
@ -214,6 +221,12 @@ int64_t xmrig::Client::submit(const JobResult &result)
|
||||
params.AddMember("nonce", StringRef(nonce), allocator);
|
||||
params.AddMember("result", StringRef(data), allocator);
|
||||
|
||||
# ifndef XMRIG_PROXY_PROJECT
|
||||
if (result.minerSignature()) {
|
||||
params.AddMember("sig", StringRef(signature), allocator);
|
||||
}
|
||||
# endif
|
||||
|
||||
if (has<EXT_ALGO>() && result.algorithm.isValid()) {
|
||||
params.AddMember("algo", StringRef(result.algorithm.shortName()), allocator);
|
||||
}
|
||||
@ -427,6 +440,13 @@ bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, 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
|
||||
|
||||
m_job.setClientId(m_rpcId);
|
||||
|
||||
if (m_job != job) {
|
||||
|
@ -137,6 +137,7 @@ private:
|
||||
std::bitset<EXT_MAX> m_extensions;
|
||||
std::shared_ptr<DnsRequest> m_dns;
|
||||
std::vector<char> m_sendBuf;
|
||||
std::vector<char> m_tempBuf;
|
||||
String m_rpcId;
|
||||
Tls *m_tls = nullptr;
|
||||
uint64_t m_expire = 0;
|
||||
|
@ -37,6 +37,8 @@
|
||||
#include "base/net/stratum/SubmitResult.h"
|
||||
#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"
|
||||
|
||||
|
||||
@ -94,16 +96,32 @@ bool xmrig::DaemonClient::isTLS() const
|
||||
|
||||
int64_t xmrig::DaemonClient::submit(const JobResult &result)
|
||||
{
|
||||
if (result.jobId != (m_blocktemplate.data() + m_blocktemplate.size() - 32)) {
|
||||
if (result.jobId != (m_blocktemplateStr.data() + m_blocktemplateStr.size() - 32)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *data = (m_apiVersion == API_DERO) ? m_blockhashingblob.data() : m_blocktemplate.data();
|
||||
char *data = (m_apiVersion == API_DERO) ? m_blockhashingblob.data() : m_blocktemplateStr.data();
|
||||
|
||||
const size_t sig_offset = m_job.nonceOffset() + m_job.nonceSize();
|
||||
|
||||
# ifdef XMRIG_PROXY_PROJECT
|
||||
memcpy(data + 78, result.nonce, 8);
|
||||
|
||||
memcpy(data + m_job.nonceOffset() * 2, result.nonce, 8);
|
||||
|
||||
if (m_blocktemplate.has_miner_signature && result.sig) {
|
||||
memcpy(data + sig_offset * 2, result.sig, 64 * 2);
|
||||
memcpy(data + m_blocktemplate.tx_pubkey_index * 2, result.sig_data, 32 * 2);
|
||||
memcpy(data + m_blocktemplate.eph_public_key_index * 2, result.sig_data + 32 * 2, 32 * 2);
|
||||
}
|
||||
|
||||
# else
|
||||
Cvt::toHex(data + 78, 8, reinterpret_cast<const uint8_t *>(&result.nonce), 4);
|
||||
|
||||
Cvt::toHex(data + m_job.nonceOffset() * 2, 8, reinterpret_cast<const uint8_t*>(&result.nonce), 4);
|
||||
|
||||
if (m_blocktemplate.has_miner_signature) {
|
||||
Cvt::toHex(data + sig_offset * 2, 128, result.minerSignature(), 64);
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
using namespace rapidjson;
|
||||
@ -111,11 +129,11 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result)
|
||||
|
||||
Value params(kArrayType);
|
||||
if (m_apiVersion == API_DERO) {
|
||||
params.PushBack(m_blocktemplate.toJSON(), doc.GetAllocator());
|
||||
params.PushBack(m_blocktemplateStr.toJSON(), doc.GetAllocator());
|
||||
params.PushBack(m_blockhashingblob.toJSON(), doc.GetAllocator());
|
||||
}
|
||||
else {
|
||||
params.PushBack(m_blocktemplate.toJSON(), doc.GetAllocator());
|
||||
params.PushBack(m_blocktemplateStr.toJSON(), doc.GetAllocator());
|
||||
}
|
||||
|
||||
JsonRequest::create(doc, m_sequence, "submitblock", params);
|
||||
@ -241,31 +259,129 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value ¶ms, int *code)
|
||||
|
||||
String blocktemplate = Json::getString(params, kBlocktemplateBlob);
|
||||
|
||||
if (blocktemplate.isNull()) {
|
||||
LOG_ERR("Empty block template received from daemon");
|
||||
*code = 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
m_blockhashingblob = Json::getString(params, "blockhashing_blob");
|
||||
|
||||
if (m_blocktemplate.has_miner_signature) {
|
||||
if (m_pool.spendSecretKey().isEmpty()) {
|
||||
LOG_ERR("Secret spend key is not set");
|
||||
*code = 4;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_pool.spendSecretKey().size() != 64) {
|
||||
LOG_ERR("Secret spend key has invalid length. It must be 64 hex characters.");
|
||||
*code = 5;
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
# 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
WalletAddress user_address;
|
||||
if (!user_address.Decode(m_pool.user())) {
|
||||
LOG_ERR("Invalid wallet address.");
|
||||
*code = 10;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcmp(user_address.public_spend_key, public_spendkey, sizeof(public_spendkey)) != 0) {
|
||||
LOG_ERR("Wallet address and spend key don't match.");
|
||||
*code = 11;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcmp(user_address.public_view_key, public_viewkey, sizeof(public_viewkey)) != 0) {
|
||||
LOG_ERR("Wallet address and view key don't match.");
|
||||
*code = 12;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t eph_secret_key[32];
|
||||
derive_secret_key(derivation, 0, secret_spendkey, eph_secret_key);
|
||||
|
||||
job.setEphemeralKeys(m_blocktemplate.raw_blob.data() + m_blocktemplate.eph_public_key_index, eph_secret_key);
|
||||
# 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_pool.coin().isValid()) {
|
||||
uint8_t blobVersion = 0;
|
||||
Cvt::fromHex(&blobVersion, 1, m_blockhashingblob.data(), 2);
|
||||
job.setAlgorithm(m_pool.coin().algorithm(blobVersion));
|
||||
if (pool_coin.isValid()) {
|
||||
job.setAlgorithm(pool_coin.algorithm(m_blocktemplate.major_version));
|
||||
}
|
||||
|
||||
if (blocktemplate.isNull() || !job.setBlob(m_blockhashingblob)) {
|
||||
*code = 4;
|
||||
if (!job.setBlob(m_blockhashingblob)) {
|
||||
*code = 3;
|
||||
return false;
|
||||
}
|
||||
|
||||
job.setSeedHash(Json::getString(params, "seed_hash"));
|
||||
job.setHeight(Json::getUint64(params, kHeight));
|
||||
job.setDiff(Json::getUint64(params, "difficulty"));
|
||||
|
||||
job.setId(blocktemplate.data() + blocktemplate.size() - 32);
|
||||
|
||||
m_job = std::move(job);
|
||||
m_blocktemplate = std::move(blocktemplate);
|
||||
m_prevHash = Json::getString(params, "prev_hash");
|
||||
m_job = std::move(job);
|
||||
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
|
||||
@ -315,7 +431,16 @@ bool xmrig::DaemonClient::parseResponse(int64_t id, const rapidjson::Value &resu
|
||||
return true;
|
||||
}
|
||||
|
||||
if (handleSubmitResponse(id)) {
|
||||
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)) {
|
||||
getBlockTemplate();
|
||||
return true;
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "base/kernel/interfaces/ITimerListener.h"
|
||||
#include "base/net/stratum/BaseClient.h"
|
||||
#include "base/tools/Object.h"
|
||||
#include "base/tools/cryptonote/BlockTemplate.h"
|
||||
|
||||
|
||||
#include <memory>
|
||||
@ -83,7 +84,7 @@ private:
|
||||
} m_apiVersion = API_MONERO;
|
||||
|
||||
std::shared_ptr<IHttpListener> m_httpListener;
|
||||
String m_blocktemplate;
|
||||
String m_blocktemplateStr;
|
||||
String m_blockhashingblob;
|
||||
String m_prevHash;
|
||||
String m_tlsFingerprint;
|
||||
@ -91,6 +92,8 @@ private:
|
||||
Timer *m_timer;
|
||||
uint64_t m_blocktemplateRequestHeight = 0;
|
||||
String m_blocktemplateRequestHash;
|
||||
|
||||
BlockTemplate m_blocktemplate;
|
||||
};
|
||||
|
||||
|
||||
|
@ -32,6 +32,9 @@
|
||||
#include "base/net/stratum/Job.h"
|
||||
#include "base/tools/Buffer.h"
|
||||
#include "base/tools/Cvt.h"
|
||||
#include "base/tools/cryptonote/BlockTemplate.h"
|
||||
#include "base/tools/cryptonote/Signatures.h"
|
||||
#include "base/crypto/keccak.h"
|
||||
|
||||
|
||||
xmrig::Job::Job(bool nicehash, const Algorithm &algorithm, const String &clientId) :
|
||||
@ -169,6 +172,22 @@ void xmrig::Job::copy(const Job &other)
|
||||
# ifdef XMRIG_FEATURE_BENCHMARK
|
||||
m_benchSize = other.m_benchSize;
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_PROXY_PROJECT
|
||||
memcpy(m_spendSecretKey, other.m_spendSecretKey, sizeof(m_spendSecretKey));
|
||||
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 = other.m_minerTxPrefix;
|
||||
m_minerTxEphPubKeyOffset = other.m_minerTxEphPubKeyOffset;
|
||||
m_minerTxPubKeyOffset = other.m_minerTxPubKeyOffset;
|
||||
m_minerTxMerkleTreeBranch = other.m_minerTxMerkleTreeBranch;
|
||||
# else
|
||||
memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey));
|
||||
memcpy(m_ephSecretKey, other.m_ephSecretKey, sizeof(m_ephSecretKey));
|
||||
# endif
|
||||
|
||||
m_hasMinerSignature = other.m_hasMinerSignature;
|
||||
}
|
||||
|
||||
|
||||
@ -204,4 +223,95 @@ void xmrig::Job::move(Job &&other)
|
||||
# ifdef XMRIG_FEATURE_BENCHMARK
|
||||
m_benchSize = other.m_benchSize;
|
||||
# endif
|
||||
|
||||
# ifdef XMRIG_PROXY_PROJECT
|
||||
memcpy(m_spendSecretKey, other.m_spendSecretKey, sizeof(m_spendSecretKey));
|
||||
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);
|
||||
# else
|
||||
memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey));
|
||||
memcpy(m_ephSecretKey, other.m_ephSecretKey, sizeof(m_ephSecretKey));
|
||||
# endif
|
||||
|
||||
m_hasMinerSignature = other.m_hasMinerSignature;
|
||||
}
|
||||
|
||||
|
||||
#ifdef XMRIG_PROXY_PROJECT
|
||||
|
||||
|
||||
void xmrig::Job::setSpendSecretKey(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);
|
||||
}
|
||||
|
||||
|
||||
void xmrig::Job::setMinerTx(const uint8_t* begin, const uint8_t* end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, const Buffer& minerTxMerkleTreeBranch)
|
||||
{
|
||||
m_minerTxPrefix.assign(begin, end);
|
||||
m_minerTxEphPubKeyOffset = minerTxEphPubKeyOffset;
|
||||
m_minerTxPubKeyOffset = minerTxPubKeyOffset;
|
||||
m_minerTxMerkleTreeBranch = minerTxMerkleTreeBranch;
|
||||
}
|
||||
|
||||
|
||||
void xmrig::Job::generateHashingBlob(String& blob, String& signatureData) const
|
||||
{
|
||||
uint8_t* eph_public_key = m_minerTxPrefix.data() + m_minerTxEphPubKeyOffset;
|
||||
uint8_t* txkey_pub = m_minerTxPrefix.data() + m_minerTxPubKeyOffset;
|
||||
|
||||
uint8_t txkey_sec[32];
|
||||
|
||||
generate_keys(txkey_pub, txkey_sec);
|
||||
|
||||
uint8_t derivation[32];
|
||||
|
||||
generate_key_derivation(m_viewPublicKey, txkey_sec, derivation);
|
||||
derive_public_key(derivation, 0, m_spendPublicKey, eph_public_key);
|
||||
|
||||
uint8_t buf[32 * 3] = {};
|
||||
memcpy(buf, txkey_pub, 32);
|
||||
memcpy(buf + 32, eph_public_key, 32);
|
||||
|
||||
generate_key_derivation(txkey_pub, m_viewSecretKey, derivation);
|
||||
derive_secret_key(derivation, 0, m_spendSecretKey, buf + 64);
|
||||
|
||||
signatureData = xmrig::Cvt::toHex(buf, sizeof(buf));
|
||||
|
||||
uint8_t root_hash[32];
|
||||
const uint8_t* p = m_minerTxPrefix.data();
|
||||
xmrig::BlockTemplate::CalculateRootHash(p, p + m_minerTxPrefix.size(), m_minerTxMerkleTreeBranch, root_hash);
|
||||
|
||||
blob = rawBlob();
|
||||
const uint64_t offset = nonceOffset() + nonceSize() + BlockTemplate::SIGNATURE_SIZE + 2 /* vote */;
|
||||
xmrig::Cvt::toHex(blob.data() + offset * 2, 64, root_hash, 32);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
void xmrig::Job::generateMinerSignature(const uint8_t* blob, size_t size, uint8_t* out_sig) const
|
||||
{
|
||||
uint8_t tmp[kMaxBlobSize];
|
||||
memcpy(tmp, blob, size);
|
||||
|
||||
// Fill signature with zeros
|
||||
memset(tmp + nonceOffset() + nonceSize(), 0, BlockTemplate::SIGNATURE_SIZE);
|
||||
|
||||
uint8_t prefix_hash[32];
|
||||
xmrig::keccak(tmp, static_cast<int>(size), prefix_hash, sizeof(prefix_hash));
|
||||
xmrig::generate_signature(prefix_hash, m_ephPublicKey, m_ephSecretKey, out_sig);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -82,7 +82,7 @@ public:
|
||||
inline uint32_t backend() const { return m_backend; }
|
||||
inline uint64_t diff() const { return m_diff; }
|
||||
inline uint64_t height() const { return m_height; }
|
||||
inline uint64_t nonceMask() const { return isNicehash() ? 0xFFFFFFULL : (nonceSize() == sizeof(uint64_t) ? (-1ULL >> (extraNonce().size() * 4)): 0xFFFFFFFFULL); }
|
||||
inline uint64_t nonceMask() const { return isNicehash() ? 0xFFFFFFULL : (nonceSize() == sizeof(uint64_t) ? (static_cast<uint64_t>(-1LL) >> (extraNonce().size() * 4)) : 0xFFFFFFFFULL); }
|
||||
inline uint64_t target() const { return m_target; }
|
||||
inline uint8_t *blob() { return m_blob; }
|
||||
inline uint8_t fixedByte() const { return *(m_blob + 42); }
|
||||
@ -116,6 +116,25 @@ public:
|
||||
inline void setBenchSize(uint32_t size) { m_benchSize = size; }
|
||||
# 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;
|
||||
# else
|
||||
inline const uint8_t* ephSecretKey() const { return m_hasMinerSignature ? m_ephSecretKey : nullptr; }
|
||||
|
||||
inline void setEphemeralKeys(uint8_t* pub_key, uint8_t* sec_key)
|
||||
{
|
||||
m_hasMinerSignature = true;
|
||||
memcpy(m_ephPublicKey, pub_key, sizeof(m_ephSecretKey));
|
||||
memcpy(m_ephSecretKey, sec_key, sizeof(m_ephSecretKey));
|
||||
}
|
||||
|
||||
void generateMinerSignature(const uint8_t* blob, size_t size, uint8_t* out_sig) const;
|
||||
# endif
|
||||
|
||||
inline bool hasMinerSignature() const { return m_hasMinerSignature; }
|
||||
|
||||
private:
|
||||
void copy(const Job &other);
|
||||
void move(Job &&other);
|
||||
@ -139,8 +158,24 @@ private:
|
||||
char m_rawBlob[kMaxBlobSize * 2 + 8]{};
|
||||
char m_rawTarget[24]{};
|
||||
String m_rawSeedHash;
|
||||
|
||||
// Miner signatures
|
||||
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;
|
||||
Buffer m_minerTxMerkleTreeBranch;
|
||||
# else
|
||||
// Miner signatures
|
||||
uint8_t m_ephPublicKey[32]{};
|
||||
uint8_t m_ephSecretKey[32]{};
|
||||
# endif
|
||||
|
||||
bool m_hasMinerSignature = false;
|
||||
|
||||
# ifdef XMRIG_FEATURE_BENCHMARK
|
||||
uint32_t m_benchSize = 0;
|
||||
# endif
|
||||
|
@ -78,6 +78,7 @@ const char *Pool::kSubmitToOrigin = "submit-to-origin";
|
||||
const char *Pool::kTls = "tls";
|
||||
const char *Pool::kUrl = "url";
|
||||
const char *Pool::kUser = "user";
|
||||
const char *Pool::kSpendSecretKey = "spend-secret-key";
|
||||
const char *Pool::kNicehashHost = "nicehash.com";
|
||||
|
||||
|
||||
@ -92,12 +93,13 @@ xmrig::Pool::Pool(const char *url) :
|
||||
}
|
||||
|
||||
|
||||
xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, bool tls, Mode mode) :
|
||||
xmrig::Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, const char* spendSecretKey, int keepAlive, bool nicehash, bool tls, Mode mode) :
|
||||
m_keepAlive(keepAlive),
|
||||
m_mode(mode),
|
||||
m_flags(1 << FLAG_ENABLED),
|
||||
m_password(password),
|
||||
m_user(user),
|
||||
m_spendSecretKey(spendSecretKey),
|
||||
m_pollInterval(kDefaultPollInterval),
|
||||
m_url(host, port, tls)
|
||||
{
|
||||
@ -115,15 +117,16 @@ xmrig::Pool::Pool(const rapidjson::Value &object) :
|
||||
return;
|
||||
}
|
||||
|
||||
m_user = Json::getString(object, kUser);
|
||||
m_password = Json::getString(object, kPass);
|
||||
m_rigId = Json::getString(object, kRigId);
|
||||
m_fingerprint = Json::getString(object, kFingerprint);
|
||||
m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval);
|
||||
m_algorithm = Json::getString(object, kAlgo);
|
||||
m_coin = Json::getString(object, kCoin);
|
||||
m_daemon = Json::getString(object, kSelfSelect);
|
||||
m_proxy = Json::getValue(object, kSOCKS5);
|
||||
m_user = Json::getString(object, kUser);
|
||||
m_spendSecretKey = Json::getString(object, kSpendSecretKey);
|
||||
m_password = Json::getString(object, kPass);
|
||||
m_rigId = Json::getString(object, kRigId);
|
||||
m_fingerprint = Json::getString(object, kFingerprint);
|
||||
m_pollInterval = Json::getUint64(object, kDaemonPollInterval, kDefaultPollInterval);
|
||||
m_algorithm = Json::getString(object, kAlgo);
|
||||
m_coin = Json::getString(object, kCoin);
|
||||
m_daemon = Json::getString(object, kSelfSelect);
|
||||
m_proxy = Json::getValue(object, kSOCKS5);
|
||||
|
||||
m_flags.set(FLAG_ENABLED, Json::getBool(object, kEnabled, true));
|
||||
m_flags.set(FLAG_NICEHASH, Json::getBool(object, kNicehash) || m_url.host().contains(kNicehashHost));
|
||||
@ -270,6 +273,10 @@ rapidjson::Value xmrig::Pool::toJSON(rapidjson::Document &doc) const
|
||||
obj.AddMember(StringRef(kUrl), url().toJSON(), allocator);
|
||||
obj.AddMember(StringRef(kUser), m_user.toJSON(), allocator);
|
||||
|
||||
if (!m_spendSecretKey.isEmpty()) {
|
||||
obj.AddMember(StringRef(kSpendSecretKey), m_spendSecretKey.toJSON(), allocator);
|
||||
}
|
||||
|
||||
if (m_mode != MODE_DAEMON) {
|
||||
obj.AddMember(StringRef(kPass), m_password.toJSON(), allocator);
|
||||
obj.AddMember(StringRef(kRigId), m_rigId.toJSON(), allocator);
|
||||
|
@ -71,6 +71,7 @@ public:
|
||||
static const char *kTls;
|
||||
static const char *kUrl;
|
||||
static const char *kUser;
|
||||
static const char* kSpendSecretKey;
|
||||
static const char *kNicehashHost;
|
||||
|
||||
constexpr static int kKeepAliveTimeout = 60;
|
||||
@ -78,7 +79,7 @@ public:
|
||||
constexpr static uint64_t kDefaultPollInterval = 1000;
|
||||
|
||||
Pool() = default;
|
||||
Pool(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, bool tls, Mode mode);
|
||||
Pool(const char *host, uint16_t port, const char *user, const char *password, const char* spendSecretKey, int keepAlive, bool nicehash, bool tls, Mode mode);
|
||||
Pool(const char *url);
|
||||
Pool(const rapidjson::Value &object);
|
||||
|
||||
@ -101,6 +102,7 @@ public:
|
||||
inline const String &rigId() const { return m_rigId; }
|
||||
inline const String &url() const { return m_url.url(); }
|
||||
inline const String &user() const { return !m_user.isNull() ? m_user : kDefaultUser; }
|
||||
inline const String &spendSecretKey() const { return m_spendSecretKey; }
|
||||
inline const Url &daemon() const { return m_daemon; }
|
||||
inline int keepAlive() const { return m_keepAlive; }
|
||||
inline Mode mode() const { return m_mode; }
|
||||
@ -149,6 +151,7 @@ private:
|
||||
String m_password;
|
||||
String m_rigId;
|
||||
String m_user;
|
||||
String m_spendSecretKey;
|
||||
uint64_t m_pollInterval = kDefaultPollInterval;
|
||||
Url m_daemon;
|
||||
Url m_url;
|
||||
|
@ -57,6 +57,12 @@ public:
|
||||
|
||||
Pools();
|
||||
|
||||
# ifdef XMRIG_FEATURE_BENCHMARK
|
||||
inline bool isBenchmark() const { return !!m_benchmark; }
|
||||
# else
|
||||
inline constexpr static bool isBenchmark() { return false; }
|
||||
# endif
|
||||
|
||||
inline const std::vector<Pool> &data() const { return m_data; }
|
||||
inline int retries() const { return m_retries; }
|
||||
inline int retryPause() const { return m_retryPause; }
|
||||
|
@ -61,7 +61,8 @@ xmrig::BenchClient::BenchClient(const std::shared_ptr<BenchConfig> &benchmark, I
|
||||
|
||||
# ifdef XMRIG_FEATURE_HTTP
|
||||
if (m_benchmark->isSubmit()) {
|
||||
m_mode = ONLINE_BENCH;
|
||||
m_mode = ONLINE_BENCH;
|
||||
m_token = m_benchmark->token();
|
||||
|
||||
return;
|
||||
}
|
||||
@ -350,6 +351,11 @@ void xmrig::BenchClient::send(Request request)
|
||||
# endif
|
||||
|
||||
FetchRequest req(HTTP_POST, m_ip, BenchConfig::kApiPort, "/1/benchmark", doc, BenchConfig::kApiTLS, true);
|
||||
|
||||
if (!m_token.isEmpty()) {
|
||||
req.headers.insert({ "Authorization", fmt::format("Bearer {}", m_token)});
|
||||
}
|
||||
|
||||
fetch(tag(), std::move(req), m_httpListener);
|
||||
}
|
||||
break;
|
||||
|
102
src/base/tools/cryptonote/BlobReader.h
Normal file
102
src/base/tools/cryptonote/BlobReader.h
Normal file
@ -0,0 +1,102 @@
|
||||
/* XMRig
|
||||
* Copyright 2012-2013 The Cryptonote developers
|
||||
* Copyright 2014-2021 The Monero Project
|
||||
* 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
|
||||
* 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_BLOBREADER_H
|
||||
#define XMRIG_BLOBREADER_H
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
class CBlobReader
|
||||
{
|
||||
public:
|
||||
inline CBlobReader(const void* data, size_t size)
|
||||
: m_data(reinterpret_cast<const uint8_t*>(data))
|
||||
, m_size(size)
|
||||
, m_index(0)
|
||||
{}
|
||||
|
||||
inline bool operator()(uint8_t& data) { return getByte(data); }
|
||||
inline bool operator()(uint64_t& data) { return getVarint(data); }
|
||||
|
||||
template<size_t N>
|
||||
inline bool operator()(uint8_t(&data)[N])
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
if (!getByte(data[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void readItems(T& data, size_t count)
|
||||
{
|
||||
data.resize(count);
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
operator()(data[i]);
|
||||
}
|
||||
|
||||
inline size_t index() const { return m_index; }
|
||||
|
||||
private:
|
||||
inline bool getByte(uint8_t& data)
|
||||
{
|
||||
if (m_index >= m_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
data = m_data[m_index++];
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool getVarint(uint64_t& data)
|
||||
{
|
||||
uint64_t result = 0;
|
||||
uint8_t t;
|
||||
int shift = 0;
|
||||
|
||||
do {
|
||||
if (!getByte(t)) {
|
||||
return false;
|
||||
}
|
||||
result |= static_cast<uint64_t>(t & 0x7F) << shift;
|
||||
shift += 7;
|
||||
} while (t & 0x80);
|
||||
|
||||
data = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
const uint8_t* m_data;
|
||||
size_t m_size;
|
||||
size_t m_index;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace xmrig */
|
||||
|
||||
|
||||
#endif /* XMRIG_BLOBREADER_H */
|
238
src/base/tools/cryptonote/BlockTemplate.cpp
Normal file
238
src/base/tools/cryptonote/BlockTemplate.cpp
Normal file
@ -0,0 +1,238 @@
|
||||
/* XMRig
|
||||
* Copyright 2012-2013 The Cryptonote developers
|
||||
* Copyright 2014-2021 The Monero Project
|
||||
* 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "base/crypto/keccak.h"
|
||||
#include "base/tools/Cvt.h"
|
||||
#include "base/tools/cryptonote/BlobReader.h"
|
||||
#include "base/tools/cryptonote/BlockTemplate.h"
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
bool BlockTemplate::Init(const String& blockTemplate, Coin coin)
|
||||
{
|
||||
raw_blob = Cvt::fromHex(blockTemplate);
|
||||
|
||||
CBlobReader ar(raw_blob.data(), raw_blob.size());
|
||||
|
||||
// Block header
|
||||
ar(major_version);
|
||||
ar(minor_version);
|
||||
ar(timestamp);
|
||||
ar(prev_id);
|
||||
ar(nonce);
|
||||
|
||||
// Wownero block template has miner signature starting from version 18
|
||||
has_miner_signature = (coin == Coin::WOWNERO) && (major_version >= 18);
|
||||
if (has_miner_signature) {
|
||||
ar(miner_signature);
|
||||
ar(vote);
|
||||
}
|
||||
|
||||
// Miner transaction begin
|
||||
// Prefix begin
|
||||
miner_tx_prefix_begin_index = ar.index();
|
||||
|
||||
ar(tx_version);
|
||||
ar(unlock_time);
|
||||
ar(num_inputs);
|
||||
|
||||
// must be 1 input
|
||||
if (num_inputs != 1)
|
||||
return false;
|
||||
|
||||
ar(input_type);
|
||||
|
||||
// input type must be txin_gen (0xFF)
|
||||
if (input_type != 0xFF)
|
||||
return false;
|
||||
|
||||
ar(height);
|
||||
|
||||
ar(num_outputs);
|
||||
|
||||
// must be 1 output
|
||||
if (num_outputs != 1)
|
||||
return false;
|
||||
|
||||
ar(amount);
|
||||
ar(output_type);
|
||||
|
||||
// output type must be txout_to_key (2)
|
||||
if (output_type != 2)
|
||||
return false;
|
||||
|
||||
eph_public_key_index = ar.index();
|
||||
|
||||
ar(eph_public_key);
|
||||
ar(extra_size);
|
||||
|
||||
tx_pubkey_index = ar.index() + 1;
|
||||
|
||||
ar.readItems(extra, extra_size);
|
||||
|
||||
// First thing in tx_extra must be TX_EXTRA_TAG_PUBKEY
|
||||
if (extra[0] != 0x01)
|
||||
return false;
|
||||
|
||||
miner_tx_prefix_end_index = ar.index();
|
||||
// Prefix end
|
||||
|
||||
// RCT signatures (empty in miner transaction)
|
||||
ar(vin_rct_type);
|
||||
|
||||
// must be RCTTypeNull (0)
|
||||
if (vin_rct_type != 0)
|
||||
return false;
|
||||
|
||||
const size_t miner_tx_end = ar.index();
|
||||
// Miner transaction end
|
||||
|
||||
// Miner transaction must have exactly 1 byte with value 0 after the prefix
|
||||
if ((miner_tx_end != miner_tx_prefix_end_index + 1) || (raw_blob[miner_tx_prefix_end_index] != 0))
|
||||
return false;
|
||||
|
||||
// Other transaction hashes
|
||||
ar(num_hashes);
|
||||
|
||||
# ifdef XMRIG_PROXY_PROJECT
|
||||
hashes.resize((num_hashes + 1) * HASH_SIZE);
|
||||
CalculateMinerTxHash(raw_blob.data() + miner_tx_prefix_begin_index, raw_blob.data() + miner_tx_prefix_end_index, hashes.data());
|
||||
|
||||
for (uint64_t i = 1; i <= num_hashes; ++i) {
|
||||
uint8_t h[HASH_SIZE];
|
||||
ar(h);
|
||||
memcpy(hashes.data() + i * HASH_SIZE, h, HASH_SIZE);
|
||||
}
|
||||
|
||||
CalculateMerkleTreeHash();
|
||||
# endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void BlockTemplate::CalculateMinerTxHash(const uint8_t* prefix_begin, const uint8_t* prefix_end, uint8_t* hash)
|
||||
{
|
||||
uint8_t hashes[HASH_SIZE * 3];
|
||||
|
||||
// Calculate 3 partial hashes
|
||||
|
||||
// 1. Prefix
|
||||
keccak(prefix_begin, static_cast<int>(prefix_end - prefix_begin), hashes, HASH_SIZE);
|
||||
|
||||
// 2. Base RCT, single 0 byte in miner tx
|
||||
static const uint8_t known_second_hash[HASH_SIZE] = {
|
||||
188,54,120,158,122,30,40,20,54,70,66,41,130,143,129,125,102,18,247,180,119,214,101,145,255,150,169,224,100,188,201,138
|
||||
};
|
||||
memcpy(hashes + HASH_SIZE, known_second_hash, HASH_SIZE);
|
||||
|
||||
// 3. Prunable RCT, empty in miner tx
|
||||
memset(hashes + HASH_SIZE * 2, 0, HASH_SIZE);
|
||||
|
||||
// Calculate miner transaction hash
|
||||
keccak(hashes, sizeof(hashes), hash, HASH_SIZE);
|
||||
}
|
||||
|
||||
|
||||
void BlockTemplate::CalculateMerkleTreeHash()
|
||||
{
|
||||
miner_tx_merkle_tree_branch.clear();
|
||||
|
||||
const uint64_t count = num_hashes + 1;
|
||||
uint8_t* h = hashes.data();
|
||||
|
||||
if (count == 1) {
|
||||
memcpy(root_hash, h, HASH_SIZE);
|
||||
}
|
||||
else if (count == 2) {
|
||||
miner_tx_merkle_tree_branch.insert(miner_tx_merkle_tree_branch.end(), h + HASH_SIZE, h + HASH_SIZE * 2);
|
||||
keccak(h, HASH_SIZE * 2, root_hash, HASH_SIZE);
|
||||
}
|
||||
else {
|
||||
size_t i, j, cnt;
|
||||
|
||||
for (i = 0, cnt = 1; cnt <= count; ++i, cnt <<= 1) {}
|
||||
|
||||
cnt >>= 1;
|
||||
|
||||
miner_tx_merkle_tree_branch.reserve(HASH_SIZE * (i - 1));
|
||||
|
||||
Buffer ints(cnt * HASH_SIZE);
|
||||
memcpy(ints.data(), h, (cnt * 2 - count) * HASH_SIZE);
|
||||
|
||||
for (i = cnt * 2 - count, j = cnt * 2 - count; j < cnt; i += 2, ++j) {
|
||||
if (i == 0) {
|
||||
miner_tx_merkle_tree_branch.insert(miner_tx_merkle_tree_branch.end(), h + HASH_SIZE, h + HASH_SIZE * 2);
|
||||
}
|
||||
keccak(h + i * HASH_SIZE, HASH_SIZE * 2, ints.data() + j * HASH_SIZE, HASH_SIZE);
|
||||
}
|
||||
|
||||
while (cnt > 2) {
|
||||
cnt >>= 1;
|
||||
for (i = 0, j = 0; j < cnt; i += 2, ++j) {
|
||||
if (i == 0) {
|
||||
miner_tx_merkle_tree_branch.insert(miner_tx_merkle_tree_branch.end(), ints.data() + HASH_SIZE, ints.data() + HASH_SIZE * 2);
|
||||
}
|
||||
keccak(ints.data() + i * HASH_SIZE, HASH_SIZE * 2, ints.data() + j * HASH_SIZE, HASH_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
miner_tx_merkle_tree_branch.insert(miner_tx_merkle_tree_branch.end(), ints.data() + HASH_SIZE, ints.data() + HASH_SIZE * 2);
|
||||
keccak(ints.data(), HASH_SIZE * 2, root_hash, HASH_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BlockTemplate::CalculateRootHash(const uint8_t* prefix_begin, const uint8_t* prefix_end, const Buffer& miner_tx_merkle_tree_branch, uint8_t* root_hash)
|
||||
{
|
||||
CalculateMinerTxHash(prefix_begin, prefix_end, root_hash);
|
||||
|
||||
for (size_t i = 0; i < miner_tx_merkle_tree_branch.size(); i += HASH_SIZE) {
|
||||
uint8_t h[HASH_SIZE * 2];
|
||||
|
||||
memcpy(h, root_hash, HASH_SIZE);
|
||||
memcpy(h + HASH_SIZE, miner_tx_merkle_tree_branch.data() + i, HASH_SIZE);
|
||||
|
||||
keccak(h, HASH_SIZE * 2, root_hash, HASH_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BlockTemplate::GenerateHashingBlob()
|
||||
{
|
||||
hashingBlob.clear();
|
||||
hashingBlob.reserve(miner_tx_prefix_begin_index + HASH_SIZE + 3);
|
||||
|
||||
hashingBlob.assign(raw_blob.begin(), raw_blob.begin() + miner_tx_prefix_begin_index);
|
||||
hashingBlob.insert(hashingBlob.end(), root_hash, root_hash + HASH_SIZE);
|
||||
|
||||
uint64_t k = num_hashes + 1;
|
||||
while (k >= 0x80) {
|
||||
hashingBlob.emplace_back((static_cast<uint8_t>(k) & 0x7F) | 0x80);
|
||||
k >>= 7;
|
||||
}
|
||||
hashingBlob.emplace_back(static_cast<uint8_t>(k));
|
||||
}
|
||||
|
||||
|
||||
} /* namespace xmrig */
|
94
src/base/tools/cryptonote/BlockTemplate.h
Normal file
94
src/base/tools/cryptonote/BlockTemplate.h
Normal file
@ -0,0 +1,94 @@
|
||||
/* XMRig
|
||||
* Copyright 2012-2013 The Cryptonote developers
|
||||
* Copyright 2014-2021 The Monero Project
|
||||
* 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
|
||||
* 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_BLOCKTEMPLATE_H
|
||||
#define XMRIG_BLOCKTEMPLATE_H
|
||||
|
||||
|
||||
#include "base/crypto/Coin.h"
|
||||
#include "base/tools/Buffer.h"
|
||||
#include "base/tools/String.h"
|
||||
|
||||
|
||||
namespace xmrig {
|
||||
|
||||
|
||||
struct BlockTemplate
|
||||
{
|
||||
enum {
|
||||
HASH_SIZE = 32,
|
||||
KEY_SIZE = 32,
|
||||
SIGNATURE_SIZE = 64,
|
||||
NONCE_SIZE = 4,
|
||||
};
|
||||
|
||||
Buffer raw_blob;
|
||||
size_t eph_public_key_index;
|
||||
size_t tx_pubkey_index;
|
||||
size_t miner_tx_prefix_begin_index;
|
||||
size_t miner_tx_prefix_end_index;
|
||||
|
||||
// Block header
|
||||
uint8_t major_version;
|
||||
uint8_t minor_version;
|
||||
uint64_t timestamp;
|
||||
uint8_t prev_id[HASH_SIZE];
|
||||
uint8_t nonce[NONCE_SIZE];
|
||||
|
||||
bool has_miner_signature;
|
||||
uint8_t miner_signature[SIGNATURE_SIZE];
|
||||
uint8_t vote[2];
|
||||
|
||||
// Miner tx
|
||||
uint64_t tx_version;
|
||||
uint64_t unlock_time;
|
||||
uint64_t num_inputs;
|
||||
uint8_t input_type;
|
||||
uint64_t height;
|
||||
uint64_t num_outputs;
|
||||
uint64_t amount;
|
||||
uint8_t output_type;
|
||||
uint8_t eph_public_key[KEY_SIZE];
|
||||
uint64_t extra_size;
|
||||
Buffer extra;
|
||||
uint8_t vin_rct_type;
|
||||
|
||||
// Transaction hashes
|
||||
uint64_t num_hashes;
|
||||
Buffer hashes;
|
||||
|
||||
Buffer miner_tx_merkle_tree_branch;
|
||||
uint8_t root_hash[HASH_SIZE];
|
||||
|
||||
Buffer hashingBlob;
|
||||
|
||||
bool Init(const String& blockTemplate, Coin coin);
|
||||
|
||||
static void CalculateMinerTxHash(const uint8_t* prefix_begin, const uint8_t* prefix_end, uint8_t* hash);
|
||||
static void CalculateRootHash(const uint8_t* prefix_begin, const uint8_t* prefix_end, const Buffer& miner_tx_merkle_tree_branch, uint8_t* root_hash);
|
||||
void CalculateMerkleTreeHash();
|
||||
void GenerateHashingBlob();
|
||||
};
|
||||
|
||||
|
||||
} /* namespace xmrig */
|
||||
|
||||
|
||||
#endif /* XMRIG_BLOCKTEMPLATE_H */
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user