Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extra nonce mining mode #460

Merged
merged 5 commits into from
Jul 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ set(HEADERS
src/proxy/Server.h
src/proxy/splitters/donate/DonateMapper.h
src/proxy/splitters/donate/DonateSplitter.h
src/proxy/splitters/extra_nonce/ExtraNonceMapper.h
src/proxy/splitters/extra_nonce/ExtraNonceSplitter.h
src/proxy/splitters/extra_nonce/ExtraNonceStorage.h
src/proxy/splitters/nicehash/NonceMapper.h
src/proxy/splitters/nicehash/NonceSplitter.h
src/proxy/splitters/nicehash/NonceStorage.h
Expand Down Expand Up @@ -93,6 +96,9 @@ set(SOURCES
src/proxy/Server.cpp
src/proxy/splitters/donate/DonateMapper.cpp
src/proxy/splitters/donate/DonateSplitter.cpp
src/proxy/splitters/extra_nonce/ExtraNonceMapper.cpp
src/proxy/splitters/extra_nonce/ExtraNonceSplitter.cpp
src/proxy/splitters/extra_nonce/ExtraNonceStorage.cpp
src/proxy/splitters/nicehash/NonceMapper.cpp
src/proxy/splitters/nicehash/NonceSplitter.cpp
src/proxy/splitters/nicehash/NonceStorage.cpp
Expand Down
29 changes: 20 additions & 9 deletions src/base/net/stratum/DaemonClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ bool xmrig::DaemonClient::isTLS() const

int64_t xmrig::DaemonClient::submit(const JobResult &result)
{
if (result.jobId != (m_blocktemplateStr.data() + m_blocktemplateStr.size() - 32)) {
if (result.jobId != m_currentJobId) {
return -1;
}

Expand All @@ -114,6 +114,10 @@ int64_t xmrig::DaemonClient::submit(const JobResult &result)
memcpy(data + m_blocktemplate.eph_public_key_index * 2, result.sig_data + 32 * 2, 32 * 2);
}

if (result.extra_nonce >= 0) {
Cvt::toHex(data + m_blocktemplate.tx_extra_nonce_index * 2, 8, reinterpret_cast<const uint8_t*>(&result.extra_nonce), 4);
}

# else

Cvt::toHex(data + m_job.nonceOffset() * 2, 8, reinterpret_cast<const uint8_t*>(&result.nonce), 4);
Expand Down Expand Up @@ -277,6 +281,19 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value &params, int *code)
return false;
}

# ifdef XMRIG_PROXY_PROJECT
const size_t k = m_blocktemplate.miner_tx_prefix_begin_index;
job.setMinerTx(
m_blocktemplate.raw_blob.data() + k,
m_blocktemplate.raw_blob.data() + m_blocktemplate.miner_tx_prefix_end_index,
m_blocktemplate.eph_public_key_index - k,
m_blocktemplate.tx_pubkey_index - k,
m_blocktemplate.tx_extra_nonce_index - k,
m_blocktemplate.tx_extra_nonce_size,
m_blocktemplate.miner_tx_merkle_tree_branch
);
# endif

m_blockhashingblob = Json::getString(params, "blockhashing_blob");

if (m_blocktemplate.has_miner_signature) {
Expand Down Expand Up @@ -308,13 +325,6 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value &params, int *code)

# ifdef XMRIG_PROXY_PROJECT
job.setSpendSecretKey(secret_spendkey);
job.setMinerTx(
m_blocktemplate.raw_blob.data() + m_blocktemplate.miner_tx_prefix_begin_index,
m_blocktemplate.raw_blob.data() + m_blocktemplate.miner_tx_prefix_end_index,
m_blocktemplate.eph_public_key_index - m_blocktemplate.miner_tx_prefix_begin_index,
m_blocktemplate.tx_pubkey_index - m_blocktemplate.miner_tx_prefix_begin_index,
m_blocktemplate.miner_tx_merkle_tree_branch
);
# else
uint8_t secret_viewkey[32];
derive_view_secret_key(secret_spendkey, secret_viewkey);
Expand Down Expand Up @@ -377,7 +387,8 @@ bool xmrig::DaemonClient::parseJob(const rapidjson::Value &params, int *code)
job.setHeight(Json::getUint64(params, kHeight));
job.setDiff(Json::getUint64(params, "difficulty"));

job.setId(blocktemplate.data() + blocktemplate.size() - 32);
m_currentJobId = Cvt::toHex(Cvt::randomBytes(4));
job.setId(m_currentJobId);

m_job = std::move(job);
m_blocktemplateStr = std::move(blocktemplate);
Expand Down
1 change: 1 addition & 0 deletions src/base/net/stratum/DaemonClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class DaemonClient : public BaseClient, public ITimerListener, public IHttpListe
} m_apiVersion = API_MONERO;

std::shared_ptr<IHttpListener> m_httpListener;
String m_currentJobId;
String m_blocktemplateStr;
String m_blockhashingblob;
String m_prevHash;
Expand Down
29 changes: 25 additions & 4 deletions src/base/net/stratum/Job.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ void xmrig::Job::copy(const Job &other)
m_minerTxPrefix = other.m_minerTxPrefix;
m_minerTxEphPubKeyOffset = other.m_minerTxEphPubKeyOffset;
m_minerTxPubKeyOffset = other.m_minerTxPubKeyOffset;
m_minerTxExtraNonceOffset = other.m_minerTxExtraNonceOffset;
m_minerTxExtraNonceSize = other.m_minerTxExtraNonceSize;
m_minerTxMerkleTreeBranch = other.m_minerTxMerkleTreeBranch;
# else
memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey));
Expand Down Expand Up @@ -254,6 +256,8 @@ void xmrig::Job::move(Job &&other)
m_minerTxPrefix = std::move(other.m_minerTxPrefix);
m_minerTxEphPubKeyOffset = other.m_minerTxEphPubKeyOffset;
m_minerTxPubKeyOffset = other.m_minerTxPubKeyOffset;
m_minerTxExtraNonceOffset = other.m_minerTxExtraNonceOffset;
m_minerTxExtraNonceSize = other.m_minerTxExtraNonceSize;
m_minerTxMerkleTreeBranch = std::move(other.m_minerTxMerkleTreeBranch);
# else
memcpy(m_ephPublicKey, other.m_ephPublicKey, sizeof(m_ephPublicKey));
Expand All @@ -278,16 +282,24 @@ void xmrig::Job::setSpendSecretKey(const uint8_t *key)
}


void xmrig::Job::setMinerTx(const uint8_t *begin, const uint8_t *end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, const Buffer &minerTxMerkleTreeBranch)
void xmrig::Job::setMinerTx(const uint8_t *begin, const uint8_t *end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, size_t minerTxExtraNonceOffset, size_t minerTxExtraNonceSize, const Buffer &minerTxMerkleTreeBranch)
{
m_minerTxPrefix.assign(begin, end);
m_minerTxEphPubKeyOffset = minerTxEphPubKeyOffset;
m_minerTxPubKeyOffset = minerTxPubKeyOffset;
m_minerTxExtraNonceOffset = minerTxExtraNonceOffset;
m_minerTxExtraNonceSize = minerTxExtraNonceSize;
m_minerTxMerkleTreeBranch = minerTxMerkleTreeBranch;
}


void xmrig::Job::generateHashingBlob(String &signatureData)
void xmrig::Job::setExtraNonceInMinerTx(uint32_t extra_nonce)
{
memcpy(m_minerTxPrefix.data() + m_minerTxExtraNonceOffset, &extra_nonce, std::min(m_minerTxExtraNonceSize, sizeof(uint32_t)));
}


void xmrig::Job::generateSignatureData(String &signatureData) const
{
uint8_t* eph_public_key = m_minerTxPrefix.data() + m_minerTxEphPubKeyOffset;
uint8_t* txkey_pub = m_minerTxPrefix.data() + m_minerTxPubKeyOffset;
Expand All @@ -309,13 +321,22 @@ void xmrig::Job::generateHashingBlob(String &signatureData)
derive_secret_key(derivation, 0, m_spendSecretKey, buf + 64);

signatureData = Cvt::toHex(buf, sizeof(buf));
}

void xmrig::Job::generateHashingBlob(String &blob) const
{
uint8_t root_hash[32];
const uint8_t* p = m_minerTxPrefix.data();
BlockTemplate::CalculateRootHash(p, p + m_minerTxPrefix.size(), m_minerTxMerkleTreeBranch, root_hash);

const uint64_t offset = nonceOffset() + nonceSize() + BlockTemplate::SIGNATURE_SIZE + 2 /* vote */;
Cvt::toHex(m_rawBlob + offset * 2, 64, root_hash, 32);
uint64_t root_hash_offset = nonceOffset() + nonceSize();

if (m_hasMinerSignature) {
root_hash_offset += BlockTemplate::SIGNATURE_SIZE + 2 /* vote */;
}

blob = rawBlob();
Cvt::toHex(blob.data() + root_hash_offset * 2, 64, root_hash, BlockTemplate::HASH_SIZE);
}


Expand Down
10 changes: 7 additions & 3 deletions src/base/net/stratum/Job.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,11 @@ class Job
# endif

# ifdef XMRIG_PROXY_PROJECT
void setSpendSecretKey(const 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 &signatureData);
void setSpendSecretKey(const uint8_t* key);
void setMinerTx(const uint8_t* begin, const uint8_t* end, size_t minerTxEphPubKeyOffset, size_t minerTxPubKeyOffset, size_t minerTxExtraNonceOffset, size_t minerTxExtraNonceSize, const Buffer& minerTxMerkleTreeBranch);
void setExtraNonceInMinerTx(uint32_t extra_nonce);
void generateSignatureData(String& signatureData) const;
void generateHashingBlob(String& blob) const;
# else
inline const uint8_t* ephSecretKey() const { return m_hasMinerSignature ? m_ephSecretKey : nullptr; }

Expand Down Expand Up @@ -170,6 +172,8 @@ class Job
mutable Buffer m_minerTxPrefix;
size_t m_minerTxEphPubKeyOffset = 0;
size_t m_minerTxPubKeyOffset = 0;
size_t m_minerTxExtraNonceOffset = 0;
size_t m_minerTxExtraNonceSize = 0;
Buffer m_minerTxMerkleTreeBranch;
# else
// Miner signatures
Expand Down
2 changes: 2 additions & 0 deletions src/base/tools/cryptonote/BlobReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class CBlobReader

inline size_t index() const { return m_index; }

inline void skip(size_t N) { m_index += N; }

private:
inline bool getByte(uint8_t& data)
{
Expand Down
30 changes: 26 additions & 4 deletions src/base/tools/cryptonote/BlockTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,35 @@ bool BlockTemplate::Init(const String& blockTemplate, Coin coin)
ar(eph_public_key);
ar(extra_size);

tx_pubkey_index = ar.index() + 1;
const uint64_t tx_extra_index = ar.index();

ar.readItems(extra, extra_size);

// First thing in tx_extra must be TX_EXTRA_TAG_PUBKEY
if (extra[0] != 0x01)
return false;
CBlobReader ar_extra(extra.data(), extra_size);

tx_extra_nonce_size = 0;
tx_extra_nonce_index = 0;

while (ar_extra.index() < extra_size) {
uint64_t extra_tag;
ar_extra(extra_tag);

switch (extra_tag) {
case 0x01: // TX_EXTRA_TAG_PUBKEY
tx_pubkey_index = tx_extra_index + ar_extra.index();
ar_extra.skip(KEY_SIZE);
break;

case 0x02: // TX_EXTRA_NONCE
ar_extra(tx_extra_nonce_size);
tx_extra_nonce_index = tx_extra_index + ar_extra.index();
ar_extra.skip(tx_extra_nonce_size);
break;

default:
return false; // TODO: handle other tags
}
}

miner_tx_prefix_end_index = ar.index();
// Prefix end
Expand Down
2 changes: 2 additions & 0 deletions src/base/tools/cryptonote/BlockTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ struct BlockTemplate
Buffer raw_blob;
size_t eph_public_key_index;
size_t tx_pubkey_index;
uint64_t tx_extra_nonce_size;
size_t tx_extra_nonce_index;
size_t miner_tx_prefix_begin_index;
size_t miner_tx_prefix_end_index;

Expand Down
2 changes: 1 addition & 1 deletion src/core/config/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
namespace xmrig {


static const std::array<const char *, 2> modeNames = { "nicehash", "simple" };
static const std::array<const char *, 3> modeNames = { "nicehash", "simple", "extra_nonce"};


} // namespace xmrig
Expand Down
3 changes: 2 additions & 1 deletion src/core/config/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ class Config : public BaseConfig
public:
enum Mode {
NICEHASH_MODE,
SIMPLE_MODE
SIMPLE_MODE,
EXTRA_NONCE_MODE,
};

Config() = default;
Expand Down
5 changes: 3 additions & 2 deletions src/net/JobResult.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@
#include <cstdio>


xmrig::JobResult::JobResult(int64_t id, const char *jobId, const char *nonce, const char *result, const xmrig::Algorithm &algorithm, const char* sig, const char* sig_data) :
xmrig::JobResult::JobResult(int64_t id, const char *jobId, const char *nonce, const char *result, const xmrig::Algorithm &algorithm, const char* sig, const char* sig_data, int64_t extra_nonce) :
algorithm(algorithm),
nonce(nonce),
result(result),
sig(sig),
sig_data(sig_data),
id(id),
jobId(jobId)
jobId(jobId),
extra_nonce(extra_nonce)
{
if (result && strlen(result) == 64) {
uint64_t target = 0;
Expand Down
17 changes: 9 additions & 8 deletions src/net/JobResult.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,24 +37,25 @@ class JobResult
static constexpr uint32_t backend = 0;

JobResult() = default;
JobResult(int64_t id, const char *jobId, const char *nonce, const char *result, const xmrig::Algorithm &algorithm, const char* sig, const char* sig_data);
JobResult(int64_t id, const char *jobId, const char *nonce, const char *result, const xmrig::Algorithm &algorithm, const char* sig, const char* sig_data, int64_t extra_nonce);

bool isCompatible(uint8_t fixedByte) const;
bool isValid() const;

inline uint64_t actualDiff() const { return m_actualDiff; }

Algorithm algorithm;
const char *nonce = nullptr;
const char *result = nullptr;
const char *sig = nullptr;
const char *sig_data = nullptr;
const int64_t id = 0;
const char *nonce = nullptr;
const char *result = nullptr;
const char *sig = nullptr;
const char *sig_data = nullptr;
const int64_t id = 0;
const int64_t extra_nonce = -1;
String jobId;
uint64_t diff = 0;
uint64_t diff = 0;

private:
uint64_t m_actualDiff = 0;
uint64_t m_actualDiff = 0;
};


Expand Down
21 changes: 17 additions & 4 deletions src/proxy/Miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ void xmrig::Miner::replyWithError(int64_t id, const char *message)
}


void xmrig::Miner::setJob(Job &job)
void xmrig::Miner::setJob(Job &job, int64_t extra_nonce)
{
using namespace rapidjson;

Expand All @@ -158,14 +158,27 @@ void xmrig::Miner::setJob(Job &job)
customDiff = true;
}

const char* blob = job.rawBlob();
String tmp_blob;

if (job.hasMinerSignature()) {
job.generateHashingBlob(m_signatureData);
job.generateSignatureData(m_signatureData);
}
else if (!job.rawSigKey().isNull()) {
m_signatureData = job.rawSigKey();
}

sendJob(job.rawBlob(), job.id().data(), customDiff ? m_sendBuf : job.rawTarget(), job.algorithm().shortName(), job.height(), job.rawSeedHash(), m_signatureData);
if (extra_nonce >= 0) {
m_extraNonce = extra_nonce;
job.setExtraNonceInMinerTx(static_cast<uint32_t>(m_extraNonce));
}

if (job.hasMinerSignature() || (extra_nonce >= 0)) {
job.generateHashingBlob(tmp_blob);
blob = tmp_blob;
}

sendJob(blob, job.id().data(), customDiff ? m_sendBuf : job.rawTarget(), job.algorithm().shortName(), job.height(), job.rawSeedHash(), m_signatureData);
}


Expand Down Expand Up @@ -237,7 +250,7 @@ bool xmrig::Miner::parseRequest(int64_t id, const char *method, const rapidjson:

Algorithm algorithm(Json::getString(params, "algo"));

SubmitEvent *event = SubmitEvent::create(this, id, Json::getString(params, "job_id"), Json::getString(params, "nonce"), Json::getString(params, "result"), algorithm, Json::getString(params, "sig"), m_signatureData);
SubmitEvent *event = SubmitEvent::create(this, id, Json::getString(params, "job_id"), Json::getString(params, "nonce"), Json::getString(params, "result"), algorithm, Json::getString(params, "sig"), m_signatureData, m_extraNonce);

if (!event->request.isValid() || event->request.actualDiff() < diff()) {
event->reject(Error::LowDifficulty);
Expand Down
3 changes: 2 additions & 1 deletion src/proxy/Miner.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class Miner : public ILineListener
bool accept(uv_stream_t *server);
void forwardJob(const Job &job, const char *algo, const char *sig_key);
void replyWithError(int64_t id, const char *message);
void setJob(Job &job);
void setJob(Job &job, int64_t extra_nonce = -1);
void success(int64_t id, const char *status);

inline bool hasExtension(Extension ext) const noexcept { return m_extensions.test(ext); }
Expand Down Expand Up @@ -156,6 +156,7 @@ class Miner : public ILineListener
uint64_t m_timestamp;
uint64_t m_tx = 0;
uint8_t m_fixedByte = 0;
int64_t m_extraNonce = -1;
uintptr_t m_key;
uv_tcp_t *m_socket;

Expand Down
Loading