Merge pull request #2445 from SChernykh/miner_signature
Support for solo mining with miner signatures (Wownero)
This commit is contained in:
commit
6e2a84a46c
36 changed files with 6234 additions and 115 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue