1
0
mirror of https://github.com/xmrig/xmrig.git synced 2025-12-07 16:05:05 -05:00

Compare commits

...

30 Commits

Author SHA1 Message Date
xmrig
b6bf6d9bc9 Update CHANGELOG.md 2017-07-20 02:56:07 +03:00
XMRig
3d9be9484d Merge branch 'dev'
# Conflicts:
#	src/version.h
2017-07-20 00:54:03 +03:00
XMRig
35fd43a6b4 Changed donation address, new xmrig-proxy is coming soon. 2017-07-19 23:57:03 +03:00
xmrig
294453fdc1 Update CHANGELOG.md 2017-07-19 23:54:50 +03:00
XMRig
30a7f9f7f5 Backport crypto changes from Dead2 xmr-stak-cpu fork. 2017-07-19 21:02:38 +03:00
XMRig
8f38462bbe #40 Fix crash on Linux. 2017-07-19 04:28:59 +03:00
XMRig
ebf54c6d04 Fix warnings on Linux. 2017-07-18 22:38:38 +03:00
XMRig
d7659b5093 Fixed %lld and %llu related warnings. 2017-07-18 20:20:29 +03:00
XMRig
e00c568ae9 Fix OS X build. 2017-07-18 14:09:20 +03:00
XMRig
a3988374f0 Fixed graceful shutdown. 2017-07-18 05:20:36 +03:00
XMRig
9732636155 Fixed bug, login request was contain malformed JSON if username or password has some special characters for example \. 2017-07-18 01:49:04 +03:00
XMRig
986aee4297 Better support for Round Robin DNS, related https://github.com/fireice-uk/xmr-stak-cpu/pull/220 2017-07-17 23:35:36 +03:00
XMRig
66d3e96a1a Sync changes with upcoming xmrig-proxy project. 2017-07-17 21:57:03 +03:00
XMRig
9f4e1ee373 Update version. 2017-07-14 21:26:22 +03:00
xmrig
ff0c6b6365 Update CHANGELOG.md 2017-07-14 21:22:48 +03:00
XMRig
7397efaf6d Merge branch 'master' of github.com:xmrig/xmrig 2017-07-14 21:16:05 +03:00
XMRig
aadc15ce66 Ignore duplicated job received from pool, with warning message. 2017-07-14 21:06:08 +03:00
XMRig
ad7c925a1a Merge branch 'dev' 2017-07-14 20:54:32 +03:00
XMRig
57be6f94bb Small code cleanup. 2017-07-13 18:02:48 +03:00
xmrig
35b188762c Update README.md 2017-07-12 14:02:07 +03:00
XMRig
7c6e429854 Improved pause/resume mechanism. 2017-07-10 21:42:28 +03:00
XMRig
c15aefd968 Merge branch 'master' into dev 2017-07-10 18:53:39 +03:00
XMRig
4a712354f1 #28 Fixed Alpine Linux support. 2017-07-07 07:15:58 +03:00
xmrig
4545c84a11 Update CHANGELOG.md 2017-07-06 10:05:36 +03:00
XMRig
a66297bed8 Merge branch 'master' into dev 2017-07-06 09:36:16 +03:00
XMRig
f4dadfd90b Improve nicehash detection. 2017-07-05 07:54:21 +03:00
XMRig
955134b162 #27 Fix possibility crash on 32bit. 2017-07-05 07:20:28 +03:00
XMRig
68795137da Merge branch 'master' into dev 2017-07-04 14:56:40 +03:00
XMRig
6ed2d61586 Probably fix OS X support. 2017-07-03 11:02:32 +03:00
xmrig
a96782218f Update README.md 2017-07-03 07:24:56 +03:00
37 changed files with 461 additions and 1527 deletions

View File

@@ -1,3 +1,16 @@
# v2.1.0
- [#40](https://github.com/xmrig/xmrig/issues/40) Improved miner shutdown, fixed crash on exit for Linux and OS X.
- Fixed, login request was contain malformed JSON if username or password has some special characters for example `\`.
- [#220](https://github.com/fireice-uk/xmr-stak-cpu/pull/220) Better support for Round Robin DNS, IP address now always chosen randomly instead of stuck on first one.
- Changed donation address, new [xmrig-proxy](https://github.com/xmrig/xmrig-proxy) is coming soon.
# v2.0.2
- Better deal with possible duplicate jobs from pool, show warning and ignore duplicates.
- For Windows builds libuv updated to version 1.13.1 and gcc to 7.1.0.
# v2.0.1
- [#27](https://github.com/xmrig/xmrig/issues/27) Fixed possibility crash on 32bit systems.
# v2.0.0 # v2.0.0
- Option `--backup-url` removed, instead now possibility specify multiple pools for example: `-o example1.com:3333 -u user1 -p password1 -k -o example2.com:5555 -u user2 -o example3.com:4444 -u user3` - Option `--backup-url` removed, instead now possibility specify multiple pools for example: `-o example1.com:3333 -u user1 -p password1 -k -o example2.com:5555 -u user2 -o example3.com:4444 -u user3`
- [#15](https://github.com/xmrig/xmrig/issues/15) Added option `-l, --log-file=FILE` to write log to file. - [#15](https://github.com/xmrig/xmrig/issues/15) Added option `-l, --log-file=FILE` to write log to file.

View File

@@ -145,6 +145,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
if (WIN32) if (WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
add_definitions(/D__STDC_FORMAT_MACROS)
else() else()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
endif() endif()

View File

@@ -1,8 +1,8 @@
# XMRig # XMRig
XMRig is high performance Monero (XMR) CPU miner, with the official full Windows support. XMRig is high performance Monero (XMR) CPU miner, with the official full Windows support.
Based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of legacy code. Originally based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of legacy code, since version 1.0.0 complete rewritten from scratch on C++.
<img src="http://i.imgur.com/GdRDnAu.png" width="596" > <img src="https://i.imgur.com/OXoB10D.png" width="628" >
#### Table of contents #### Table of contents
* [Features](#features) * [Features](#features)

View File

@@ -123,6 +123,9 @@ int App::exec()
void App::close() void App::close()
{ {
m_network->stop();
Workers::stop();
uv_stop(uv_default_loop()); uv_stop(uv_default_loop());
} }
@@ -147,5 +150,6 @@ void App::onSignal(uv_signal_t *handle, int signum)
break; break;
} }
uv_signal_stop(handle);
m_self->close(); m_self->close();
} }

View File

@@ -40,6 +40,6 @@ void Cpu::init()
} }
void Cpu::setAffinity(int id, unsigned long mask) void Cpu::setAffinity(int id, uint64_t mask)
{ {
} }

View File

@@ -25,6 +25,7 @@
#include <pthread.h> #include <pthread.h>
#include <sched.h> #include <sched.h>
#include <unistd.h> #include <unistd.h>
#include <string.h>
#include "Cpu.h" #include "Cpu.h"

View File

@@ -22,6 +22,7 @@
*/ */
#include <inttypes.h>
#include <uv.h> #include <uv.h>
@@ -94,7 +95,7 @@ static void print_threads()
{ {
char buf[32]; char buf[32];
if (Options::i()->affinity() != -1L) { if (Options::i()->affinity() != -1L) {
snprintf(buf, 32, ", affinity=0x%llX", Options::i()->affinity()); snprintf(buf, 32, ", affinity=0x%" PRIX64, Options::i()->affinity());
} }
else { else {
buf[0] = '\0'; buf[0] = '\0';

View File

@@ -65,7 +65,7 @@ static inline void do_jh_hash(const void* input, size_t len, char* output) {
static inline void do_skein_hash(const void* input, size_t len, char* output) { static inline void do_skein_hash(const void* input, size_t len, char* output) {
skein_hash(8 * 32, static_cast<const uint8_t*>(input), 8 * len, reinterpret_cast<uint8_t*>(output)); xmr_skein(static_cast<const uint8_t*>(input), reinterpret_cast<uint8_t*>(output));
} }

View File

@@ -3,7 +3,7 @@
// A baseline Keccak (3rd round) implementation. // A baseline Keccak (3rd round) implementation.
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <memory.h>
#define HASH_DATA_AREA 136 #define HASH_DATA_AREA 136
#define KECCAK_ROUNDS 24 #define KECCAK_ROUNDS 24
@@ -24,18 +24,6 @@ const uint64_t keccakf_rndc[24] =
0x8000000000008080, 0x0000000080000001, 0x8000000080008008 0x8000000000008080, 0x0000000080000001, 0x8000000080008008
}; };
const int keccakf_rotc[24] =
{
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44
};
const int keccakf_piln[24] =
{
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
};
// update the state with given number of rounds // update the state with given number of rounds
void keccakf(uint64_t st[25], int rounds) void keccakf(uint64_t st[25], int rounds)
@@ -63,25 +51,85 @@ void keccakf(uint64_t st[25], int rounds)
// Rho Pi // Rho Pi
t = st[1]; t = st[1];
for (i = 0; i < 24; ++i) { st[ 1] = ROTL64(st[ 6], 44);
bc[0] = st[keccakf_piln[i]]; st[ 6] = ROTL64(st[ 9], 20);
st[keccakf_piln[i]] = ROTL64(t, keccakf_rotc[i]); st[ 9] = ROTL64(st[22], 61);
t = bc[0]; st[22] = ROTL64(st[14], 39);
} st[14] = ROTL64(st[20], 18);
st[20] = ROTL64(st[ 2], 62);
st[ 2] = ROTL64(st[12], 43);
st[12] = ROTL64(st[13], 25);
st[13] = ROTL64(st[19], 8);
st[19] = ROTL64(st[23], 56);
st[23] = ROTL64(st[15], 41);
st[15] = ROTL64(st[ 4], 27);
st[ 4] = ROTL64(st[24], 14);
st[24] = ROTL64(st[21], 2);
st[21] = ROTL64(st[ 8], 55);
st[ 8] = ROTL64(st[16], 45);
st[16] = ROTL64(st[ 5], 36);
st[ 5] = ROTL64(st[ 3], 28);
st[ 3] = ROTL64(st[18], 21);
st[18] = ROTL64(st[17], 15);
st[17] = ROTL64(st[11], 10);
st[11] = ROTL64(st[ 7], 6);
st[ 7] = ROTL64(st[10], 3);
st[10] = ROTL64(t, 1);
// Chi // Chi
for (j = 0; j < 25; j += 5) { // unrolled loop, where only last iteration is different
bc[0] = st[j ]; j = 0;
bc[1] = st[j + 1]; bc[0] = st[j ];
bc[2] = st[j + 2]; bc[1] = st[j + 1];
bc[3] = st[j + 3];
bc[4] = st[j + 4]; st[j ] ^= (~st[j + 1]) & st[j + 2];
st[j ] ^= (~bc[1]) & bc[2]; st[j + 1] ^= (~st[j + 2]) & st[j + 3];
st[j + 1] ^= (~bc[2]) & bc[3]; st[j + 2] ^= (~st[j + 3]) & st[j + 4];
st[j + 2] ^= (~bc[3]) & bc[4]; st[j + 3] ^= (~st[j + 4]) & bc[0];
st[j + 3] ^= (~bc[4]) & bc[0]; st[j + 4] ^= (~bc[0]) & bc[1];
st[j + 4] ^= (~bc[0]) & bc[1];
} j = 5;
bc[0] = st[j ];
bc[1] = st[j + 1];
st[j ] ^= (~st[j + 1]) & st[j + 2];
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
st[j + 3] ^= (~st[j + 4]) & bc[0];
st[j + 4] ^= (~bc[0]) & bc[1];
j = 10;
bc[0] = st[j ];
bc[1] = st[j + 1];
st[j ] ^= (~st[j + 1]) & st[j + 2];
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
st[j + 3] ^= (~st[j + 4]) & bc[0];
st[j + 4] ^= (~bc[0]) & bc[1];
j = 15;
bc[0] = st[j ];
bc[1] = st[j + 1];
st[j ] ^= (~st[j + 1]) & st[j + 2];
st[j + 1] ^= (~st[j + 2]) & st[j + 3];
st[j + 2] ^= (~st[j + 3]) & st[j + 4];
st[j + 3] ^= (~st[j + 4]) & bc[0];
st[j + 4] ^= (~bc[0]) & bc[1];
j = 20;
bc[0] = st[j ];
bc[1] = st[j + 1];
bc[2] = st[j + 2];
bc[3] = st[j + 3];
bc[4] = st[j + 4];
st[j ] ^= (~bc[1]) & bc[2];
st[j + 1] ^= (~bc[2]) & bc[3];
st[j + 2] ^= (~bc[3]) & bc[4];
st[j + 3] ^= (~bc[4]) & bc[0];
st[j + 4] ^= (~bc[0]) & bc[1];
// Iota // Iota
st[0] ^= keccakf_rndc[round]; st[0] ^= keccakf_rndc[round];
@@ -121,3 +169,8 @@ void keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen)
memcpy(md, st, mdlen); memcpy(md, st, mdlen);
} }
void keccak1600(const uint8_t *in, int inlen, uint8_t *md)
{
keccak(in, inlen, md, sizeof(state_t));
}

File diff suppressed because it is too large Load Diff

View File

@@ -44,4 +44,6 @@ typedef u08b_t SkeinBitSequence; /* bit stream type */
SkeinHashReturn skein_hash(int hashbitlen, const SkeinBitSequence *data, SkeinHashReturn skein_hash(int hashbitlen, const SkeinBitSequence *data,
SkeinDataLength databitlen, SkeinBitSequence *hashval); SkeinDataLength databitlen, SkeinBitSequence *hashval);
void xmr_skein(const SkeinBitSequence *data, SkeinBitSequence *hashval);
#endif /* ifndef _SKEIN_H_ */ #endif /* ifndef _SKEIN_H_ */

View File

@@ -37,10 +37,10 @@ class IClientListener
public: public:
virtual ~IClientListener() {} virtual ~IClientListener() {}
virtual void onClose(Client *client, int failures) = 0; virtual void onClose(Client *client, int failures) = 0;
virtual void onJobReceived(Client *client, const Job &job) = 0; virtual void onJobReceived(Client *client, const Job &job) = 0;
virtual void onLoginSuccess(Client *client) = 0; virtual void onLoginSuccess(Client *client) = 0;
virtual void onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) = 0; virtual void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) = 0;
}; };

View File

@@ -25,6 +25,9 @@
#define __ISTRATEGY_H__ #define __ISTRATEGY_H__
#include <stdint.h>
class JobResult; class JobResult;
@@ -33,10 +36,11 @@ class IStrategy
public: public:
virtual ~IStrategy() {} virtual ~IStrategy() {}
virtual bool isActive() const = 0; virtual bool isActive() const = 0;
virtual void connect() = 0; virtual int64_t submit(const JobResult &result) = 0;
virtual void resume() = 0; virtual void connect() = 0;
virtual void submit(const JobResult &result) = 0; virtual void resume() = 0;
virtual void stop() = 0;
}; };

View File

@@ -38,10 +38,10 @@ class IStrategyListener
public: public:
virtual ~IStrategyListener() {} virtual ~IStrategyListener() {}
virtual void onActive(Client *client) = 0; virtual void onActive(Client *client) = 0;
virtual void onJob(Client *client, const Job &job) = 0; virtual void onJob(Client *client, const Job &job) = 0;
virtual void onPause(IStrategy *strategy) = 0; virtual void onPause(IStrategy *strategy) = 0;
virtual void onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) = 0; virtual void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) = 0;
}; };

View File

@@ -21,23 +21,32 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <inttypes.h>
#include <iterator> #include <iterator>
#include <string.h>
#include <utility> #include <utility>
#include "log/Log.h" #include "log/Log.h"
#include "interfaces/IClientListener.h" #include "interfaces/IClientListener.h"
#include "net/Client.h" #include "net/Client.h"
#include "net/JobResult.h"
#include "net/Url.h" #include "net/Url.h"
#ifdef XMRIG_PROXY_PROJECT
# include "proxy/JobResult.h"
#else
# include "net/JobResult.h"
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
# define strncasecmp(x,y,z) _strnicmp(x,y,z) # define strncasecmp(x,y,z) _strnicmp(x,y,z)
#endif #endif
int64_t Client::m_sequence = 1;
Client::Client(int id, const char *agent, IClientListener *listener) : Client::Client(int id, const char *agent, IClientListener *listener) :
m_quiet(false), m_quiet(false),
m_agent(agent), m_agent(agent),
@@ -45,19 +54,19 @@ Client::Client(int id, const char *agent, IClientListener *listener) :
m_id(id), m_id(id),
m_retryPause(5000), m_retryPause(5000),
m_failures(0), m_failures(0),
m_sequence(1),
m_recvBufPos(0), m_recvBufPos(0),
m_state(UnconnectedState), m_state(UnconnectedState),
m_stream(nullptr), m_stream(nullptr),
m_socket(nullptr) m_socket(nullptr)
{ {
memset(m_ip, 0, sizeof(m_ip)); memset(m_ip, 0, sizeof(m_ip));
memset(&m_hints, 0, sizeof(m_hints));
m_resolver.data = m_responseTimer.data = m_retriesTimer.data = m_keepAliveTimer.data = this; m_resolver.data = m_responseTimer.data = m_retriesTimer.data = m_keepAliveTimer.data = this;
m_hints.ai_family = PF_INET; m_hints.ai_family = PF_INET;
m_hints.ai_socktype = SOCK_STREAM; m_hints.ai_socktype = SOCK_STREAM;
m_hints.ai_protocol = IPPROTO_TCP; m_hints.ai_protocol = IPPROTO_TCP;
m_hints.ai_flags = 0;
m_recvBuf.base = static_cast<char*>(malloc(kRecvBufSize)); m_recvBuf.base = static_cast<char*>(malloc(kRecvBufSize));
m_recvBuf.len = kRecvBufSize; m_recvBuf.len = kRecvBufSize;
@@ -76,6 +85,35 @@ Client::~Client()
} }
/**
* @brief Send raw data to server.
*
* @param data
*/
int64_t Client::send(char *data, size_t size)
{
LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size ? size : strlen(data), data);
if (state() != ConnectedState) {
LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state);
return -1;
}
uv_buf_t buf = uv_buf_init(data, size ? size : strlen(data));
uv_write_t *req = static_cast<uv_write_t*>(malloc(sizeof(uv_write_t)));
req->data = buf.base;
uv_write(req, m_stream, &buf, 1, [](uv_write_t *req, int status) {
free(req->data);
free(req);
});
uv_timer_start(&m_responseTimer, [](uv_timer_t *handle) { getClient(handle->data)->close(); }, kResponseTimeout, 0);
return m_sequence++;
}
void Client::connect() void Client::connect()
{ {
resolve(m_url.host()); resolve(m_url.host());
@@ -96,6 +134,8 @@ void Client::connect(const Url *url)
void Client::disconnect() void Client::disconnect()
{ {
uv_timer_stop(&m_keepAliveTimer);
uv_timer_stop(&m_responseTimer);
uv_timer_stop(&m_retriesTimer); uv_timer_stop(&m_retriesTimer);
m_failures = -1; m_failures = -1;
@@ -103,34 +143,6 @@ void Client::disconnect()
} }
/**
* @brief Send raw data to server.
*
* @param data
*/
void Client::send(char *data)
{
LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), strlen(data), data);
if (state() != ConnectedState) {
LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state);
return;
}
m_sequence++;
uv_buf_t buf = uv_buf_init(data, strlen(data));
uv_write_t *req = static_cast<uv_write_t*>(malloc(sizeof(uv_write_t)));
req->data = buf.base;
uv_write(req, m_stream, &buf, 1, [](uv_write_t *req, int status) {
free(req->data);
free(req);
});
uv_timer_start(&m_responseTimer, [](uv_timer_t *handle) { getClient(handle->data)->close(); }, kResponseTimeout, 0);
}
void Client::setUrl(const Url *url) void Client::setUrl(const Url *url)
{ {
if (!url || !url->isValid()) { if (!url || !url->isValid()) {
@@ -141,9 +153,14 @@ void Client::setUrl(const Url *url)
} }
void Client::submit(const JobResult &result) int64_t Client::submit(const JobResult &result)
{ {
char *req = static_cast<char*>(malloc(345)); char *req = static_cast<char*>(malloc(345));
# ifdef XMRIG_PROXY_PROJECT
const char *nonce = result.nonce;
const char *data = result.result;
# else
char nonce[9]; char nonce[9];
char data[65]; char data[65];
@@ -152,12 +169,13 @@ void Client::submit(const JobResult &result)
Job::toHex(result.result, 32, data); Job::toHex(result.result, 32, data);
data[64] = '\0'; data[64] = '\0';
# endif
snprintf(req, 345, "{\"id\":%llu,\"jsonrpc\":\"2.0\",\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}}\n", snprintf(req, 345, "{\"id\":%" PRIu64 ",\"jsonrpc\":\"2.0\",\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}}\n",
m_sequence, m_rpcId, result.jobId, nonce, data); m_sequence, m_rpcId, result.jobId, nonce, data);
m_results[m_sequence] = SubmitResult(result.diff); m_results[m_sequence] = SubmitResult(m_sequence, result.diff);
send(req); return send(req);
} }
@@ -184,9 +202,12 @@ bool Client::parseJob(const json_t *params, int *code)
return false; return false;
} }
m_job = std::move(job); if (m_job == job) {
LOG_WARN("[%s:%u] duplicate job received, ignore", m_url.host(), m_url.port());
return false;
}
LOG_DEBUG("[%s:%u] job: \"%s\", diff: %lld", m_url.host(), m_url.port(), job.id(), job.diff()); m_job = std::move(job);
return true; return true;
} }
@@ -235,7 +256,10 @@ void Client::close()
} }
setState(ClosingState); setState(ClosingState);
uv_close(reinterpret_cast<uv_handle_t*>(m_socket), Client::onClose);
if (uv_is_closing(reinterpret_cast<uv_handle_t*>(m_socket)) == 0) {
uv_close(reinterpret_cast<uv_handle_t*>(m_socket), Client::onClose);
}
} }
@@ -259,20 +283,34 @@ void Client::connect(struct sockaddr *addr)
uv_tcp_keepalive(m_socket, 1, 60); uv_tcp_keepalive(m_socket, 1, 60);
# endif # endif
uv_tcp_connect(req, m_socket, (const sockaddr*) addr, Client::onConnect); uv_tcp_connect(req, m_socket, reinterpret_cast<const sockaddr*>(addr), Client::onConnect);
} }
void Client::login() void Client::login()
{ {
m_sequence = 1;
m_results.clear(); m_results.clear();
const size_t size = 96 + strlen(m_url.user()) + strlen(m_url.password()) + strlen(m_agent); json_t *req = json_object();
char *req = static_cast<char*>(malloc(size)); json_object_set(req, "id", json_integer(1));
snprintf(req, size, "{\"id\":%llu,\"jsonrpc\":\"2.0\",\"method\":\"login\",\"params\":{\"login\":\"%s\",\"pass\":\"%s\",\"agent\":\"%s\"}}\n", m_sequence, m_url.user(), m_url.password(), m_agent); json_object_set(req, "jsonrpc", json_string("2.0"));
json_object_set(req, "method", json_string("login"));
send(req); json_t *params = json_object();
json_object_set(params, "login", json_string(m_url.user()));
json_object_set(params, "pass", json_string(m_url.password()));
json_object_set(params, "agent", json_string(m_agent));
json_object_set(req, "params", params);
char *buf = json_dumps(req, JSON_COMPACT);
const size_t size = strlen(buf);
buf[size] = '\n';
json_decref(req);
send(buf, size + 1);
} }
@@ -310,7 +348,7 @@ void Client::parseNotification(const char *method, const json_t *params, const j
{ {
if (json_is_object(error)) { if (json_is_object(error)) {
if (!m_quiet) { if (!m_quiet) {
LOG_ERR("[%s:%u] error: \"%s\", code: %lld", m_url.host(), m_url.port(), json_string_value(json_object_get(error, "message")), json_integer_value(json_object_get(error, "code"))); LOG_ERR("[%s:%u] error: \"%s\", code: %" PRId64, m_url.host(), m_url.port(), json_string_value(json_object_get(error, "message")), json_integer_value(json_object_get(error, "code")));
} }
return; return;
} }
@@ -339,11 +377,11 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
auto it = m_results.find(id); auto it = m_results.find(id);
if (it != m_results.end()) { if (it != m_results.end()) {
m_listener->onResultAccepted(this, it->second.diff, it->second.elapsed(), message); m_listener->onResultAccepted(this, it->second.seq, it->second.diff, it->second.elapsed(), message);
m_results.erase(it); m_results.erase(it);
} }
else if (!m_quiet) { else if (!m_quiet) {
LOG_ERR("[%s:%u] error: \"%s\", code: %lld", m_url.host(), m_url.port(), message, json_integer_value(json_object_get(error, "code"))); LOG_ERR("[%s:%u] error: \"%s\", code: %" PRId64, m_url.host(), m_url.port(), message, json_integer_value(json_object_get(error, "code")));
} }
if (id == 1 || (message && strncasecmp(message, "Unauthenticated", 15) == 0)) { if (id == 1 || (message && strncasecmp(message, "Unauthenticated", 15) == 0)) {
@@ -375,7 +413,7 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
auto it = m_results.find(id); auto it = m_results.find(id);
if (it != m_results.end()) { if (it != m_results.end()) {
m_listener->onResultAccepted(this, it->second.diff, it->second.elapsed(), nullptr); m_listener->onResultAccepted(this, it->second.seq, it->second.diff, it->second.elapsed(), nullptr);
m_results.erase(it); m_results.erase(it);
} }
} }
@@ -383,8 +421,8 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
void Client::ping() void Client::ping()
{ {
char *req = static_cast<char*>(malloc(128)); char *req = static_cast<char*>(malloc(160));
snprintf(req, 128, "{\"id\":%lld,\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId); snprintf(req, 160, "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId);
send(req); send(req);
} }
@@ -528,14 +566,26 @@ void Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res)
return client->reconnect();; return client->reconnect();;
} }
uv_ip4_name(reinterpret_cast<sockaddr_in*>(res->ai_addr), client->m_ip, 16); addrinfo *ptr = res;
std::vector<addrinfo*> ipv4;
client->connect(res->ai_addr); while (ptr != nullptr) {
if (ptr->ai_family == AF_INET) {
ipv4.push_back(ptr);
}
ptr = ptr->ai_next;
}
if (ipv4.empty()) {
LOG_ERR("[%s:%u] DNS error: \"No IPv4 records found\"", client->m_url.host(), client->m_url.port());
return client->reconnect();
}
ptr = ipv4[rand() % ipv4.size()];
uv_ip4_name(reinterpret_cast<sockaddr_in*>(ptr->ai_addr), client->m_ip, 16);
client->connect(ptr->ai_addr);
uv_freeaddrinfo(res); uv_freeaddrinfo(res);
} }
Client *Client::getClient(void *data)
{
return static_cast<Client*>(data);
}

View File

@@ -56,12 +56,12 @@ public:
Client(int id, const char *agent, IClientListener *listener); Client(int id, const char *agent, IClientListener *listener);
~Client(); ~Client();
int64_t send(char *data, size_t size = 0);
int64_t submit(const JobResult &result);
void connect(); void connect();
void connect(const Url *url); void connect(const Url *url);
void disconnect(); void disconnect();
void send(char *data);
void setUrl(const Url *url); void setUrl(const Url *url);
void submit(const JobResult &result);
inline bool isReady() const { return m_state == ConnectedState && m_failures == 0; } inline bool isReady() const { return m_state == ConnectedState && m_failures == 0; }
inline const char *host() const { return m_url.host(); } inline const char *host() const { return m_url.host(); }
@@ -96,8 +96,9 @@ private:
static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf); static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf);
static void onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res); static void onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res);
static Client *getClient(void *data); static inline Client *getClient(void *data) { return static_cast<Client*>(data); }
addrinfo m_hints;
bool m_quiet; bool m_quiet;
char m_ip[17]; char m_ip[17];
char m_rpcId[64]; char m_rpcId[64];
@@ -106,12 +107,11 @@ private:
int m_id; int m_id;
int m_retryPause; int m_retryPause;
int64_t m_failures; int64_t m_failures;
int64_t m_sequence;
Job m_job; Job m_job;
size_t m_recvBufPos; size_t m_recvBufPos;
SocketState m_state; SocketState m_state;
static int64_t m_sequence;
std::map<int64_t, SubmitResult> m_results; std::map<int64_t, SubmitResult> m_results;
struct addrinfo m_hints;
Url m_url; Url m_url;
uv_buf_t m_recvBuf; uv_buf_t m_recvBuf;
uv_getaddrinfo_t m_resolver; uv_getaddrinfo_t m_resolver;

View File

@@ -82,7 +82,20 @@ bool Job::setBlob(const char *blob)
return false; return false;
} }
return fromHex(blob, m_size * 2, m_blob); if (!fromHex(blob, m_size * 2, m_blob)) {
return false;
}
if (*nonce() != 0 && !m_nicehash) {
m_nicehash = true;
}
# ifdef XMRIG_PROXY_PROJECT
memset(m_rawBlob, 0, sizeof(m_rawBlob));
memcpy(m_rawBlob, blob, m_size * 2);
# endif
return true;
} }
@@ -130,6 +143,11 @@ bool Job::setTarget(const char *target)
return false; return false;
} }
# ifdef XMRIG_PROXY_PROJECT
memset(m_rawTarget, 0, sizeof(m_rawTarget));
memcpy(m_rawTarget, target, len);
# endif
m_diff = toDiff(m_target); m_diff = toDiff(m_target);
return true; return true;
} }
@@ -156,3 +174,9 @@ void Job::toHex(const unsigned char* in, unsigned int len, char* out)
out[i * 2 + 1] = hf_bin2hex(in[i] & 0x0F); out[i * 2 + 1] = hf_bin2hex(in[i] & 0x0F);
} }
} }
bool Job::operator==(const Job &other) const
{
return memcmp(m_id, other.m_id, sizeof(m_id)) == 0;
}

View File

@@ -50,11 +50,18 @@ public:
inline uint64_t target() const { return m_target; } inline uint64_t target() const { return m_target; }
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; } inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
# ifdef XMRIG_PROXY_PROJECT
inline char *rawBlob() { return m_rawBlob; }
inline const char *rawTarget() const { return m_rawTarget; }
# endif
static bool fromHex(const char* in, unsigned int len, unsigned char* out); static bool fromHex(const char* in, unsigned int len, unsigned char* out);
static inline uint32_t *nonce(uint8_t *blob) { return reinterpret_cast<uint32_t*>(blob + 39); } static inline uint32_t *nonce(uint8_t *blob) { return reinterpret_cast<uint32_t*>(blob + 39); }
static inline uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; } static inline uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; }
static void toHex(const unsigned char* in, unsigned int len, char* out); static void toHex(const unsigned char* in, unsigned int len, char* out);
bool operator==(const Job &other) const;
private: private:
bool m_nicehash; bool m_nicehash;
int m_poolId; int m_poolId;
@@ -63,6 +70,11 @@ private:
uint32_t m_size; uint32_t m_size;
uint64_t m_diff; uint64_t m_diff;
uint64_t m_target; uint64_t m_target;
# ifdef XMRIG_PROXY_PROJECT
VAR_ALIGN(16, char m_rawBlob[169]);
VAR_ALIGN(16, char m_rawTarget[17]);
# endif
}; };
#endif /* __JOB_H__ */ #endif /* __JOB_H__ */

View File

@@ -22,7 +22,9 @@
*/ */
#include <inttypes.h>
#include <memory> #include <memory>
#include <time.h>
#include "log/Log.h" #include "log/Log.h"
@@ -43,6 +45,8 @@ Network::Network(const Options *options) :
m_accepted(0), m_accepted(0),
m_rejected(0) m_rejected(0)
{ {
srand(time(0) ^ (uintptr_t) this);
Workers::setListener(this); Workers::setListener(this);
m_agent = userAgent(); m_agent = userAgent();
@@ -73,6 +77,16 @@ void Network::connect()
} }
void Network::stop()
{
if (m_donate) {
m_donate->stop();
}
m_strategy->stop();
}
void Network::onActive(Client *client) void Network::onActive(Client *client)
{ {
if (client->id() == -1) { if (client->id() == -1) {
@@ -97,7 +111,8 @@ void Network::onJob(Client *client, const Job &job)
void Network::onJobResult(const JobResult &result) void Network::onJobResult(const JobResult &result)
{ {
if (result.poolId == -1 && m_donate) { if (result.poolId == -1 && m_donate) {
return m_donate->submit(result); m_donate->submit(result);
return;
} }
m_strategy->submit(result); m_strategy->submit(result);
@@ -112,23 +127,27 @@ void Network::onPause(IStrategy *strategy)
} }
if (!m_strategy->isActive()) { if (!m_strategy->isActive()) {
LOG_ERR("no active pools, pause mining"); LOG_ERR("no active pools, stop mining");
return Workers::pause(); return Workers::pause();
} }
} }
void Network::onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) void Network::onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error)
{ {
if (error) { if (error) {
m_rejected++; m_rejected++;
LOG_INFO(m_options->colors() ? "\x1B[01;31mrejected\x1B[0m (%lld/%lld) diff \x1B[01;37m%u\x1B[0m \x1B[31m\"%s\"\x1B[0m \x1B[01;30m(%llu ms)" : "accepted (%lld/%lld) diff %u \"%s\" (%llu ms)", m_accepted, m_rejected, diff, error, ms); LOG_INFO(m_options->colors() ? "\x1B[01;31mrejected\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[01;37m%u\x1B[0m \x1B[31m\"%s\"\x1B[0m \x1B[01;30m(%" PRIu64 " ms)"
: "rejected (%" PRId64 "/%" PRId64 ") diff %u \"%s\" (%" PRIu64 " ms)",
m_accepted, m_rejected, diff, error, ms);
} }
else { else {
m_accepted++; m_accepted++;
LOG_INFO(m_options->colors() ? "\x1B[01;32maccepted\x1B[0m (%lld/%lld) diff \x1B[01;37m%u\x1B[0m \x1B[01;30m(%llu ms)" : "accepted (%lld/%lld) diff %u (%llu ms)", m_accepted, m_rejected, diff, ms); LOG_INFO(m_options->colors() ? "\x1B[01;32maccepted\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[01;37m%u\x1B[0m \x1B[01;30m(%" PRIu64 " ms)"
: "accepted (%" PRId64 "/%" PRId64 ") diff %u (%" PRIu64 " ms)",
m_accepted, m_rejected, diff, ms);
} }
} }

View File

@@ -29,7 +29,6 @@
#include <uv.h> #include <uv.h>
#include "interfaces/IClientListener.h"
#include "interfaces/IJobResultListener.h" #include "interfaces/IJobResultListener.h"
#include "interfaces/IStrategyListener.h" #include "interfaces/IStrategyListener.h"
@@ -46,6 +45,7 @@ public:
~Network(); ~Network();
void connect(); void connect();
void stop();
static char *userAgent(); static char *userAgent();
@@ -54,13 +54,10 @@ protected:
void onJob(Client *client, const Job &job) override; void onJob(Client *client, const Job &job) override;
void onJobResult(const JobResult &result) override; void onJobResult(const JobResult &result) override;
void onPause(IStrategy *strategy) override; void onPause(IStrategy *strategy) override;
void onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) override; void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) override;
private: private:
void addPool(const Url *url);
void setJob(Client *client, const Job &job); void setJob(Client *client, const Job &job);
void startDonate();
void stopDonate();
bool m_donateActive; bool m_donateActive;
char *m_agent; char *m_agent;

View File

@@ -31,8 +31,9 @@
class SubmitResult class SubmitResult
{ {
public: public:
inline SubmitResult() : diff(0), start(0) {} inline SubmitResult() : seq(0), diff(0), start(0) {}
inline SubmitResult(uint32_t diff) : inline SubmitResult(int64_t seq, uint32_t diff) :
seq(seq),
diff(diff) diff(diff)
{ {
start = uv_hrtime(); start = uv_hrtime();
@@ -40,6 +41,7 @@ public:
inline uint64_t elapsed() const { return (uv_hrtime() - start) / 1000000; } inline uint64_t elapsed() const { return (uv_hrtime() - start) / 1000000; }
int64_t seq;
uint32_t diff; uint32_t diff;
uint64_t start; uint64_t start;
}; };

View File

@@ -34,7 +34,7 @@ DonateStrategy::DonateStrategy(const char *agent, IStrategyListener *listener) :
m_idleTime((100 - Options::i()->donateLevel()) * 60 * 1000), m_idleTime((100 - Options::i()->donateLevel()) * 60 * 1000),
m_listener(listener) m_listener(listener)
{ {
Url *url = new Url("donate.xmrig.com", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443, Options::i()->pools().front()->user()); Url *url = new Url("fee.xmrig.com", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443, Options::i()->pools().front()->user(), nullptr, false, true);
m_client = new Client(-1, agent, this); m_client = new Client(-1, agent, this);
m_client->setUrl(url); m_client->setUrl(url);
@@ -50,15 +50,22 @@ DonateStrategy::DonateStrategy(const char *agent, IStrategyListener *listener) :
} }
int64_t DonateStrategy::submit(const JobResult &result)
{
return m_client->submit(result);
}
void DonateStrategy::connect() void DonateStrategy::connect()
{ {
m_client->connect(); m_client->connect();
} }
void DonateStrategy::submit(const JobResult &result) void DonateStrategy::stop()
{ {
m_client->submit(result); uv_timer_stop(&m_timer);
m_client->disconnect();
} }
@@ -84,9 +91,9 @@ void DonateStrategy::onLoginSuccess(Client *client)
} }
void DonateStrategy::onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) void DonateStrategy::onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error)
{ {
m_listener->onResultAccepted(client, diff, ms, error); m_listener->onResultAccepted(client, seq, diff, ms, error);
} }
@@ -96,7 +103,7 @@ void DonateStrategy::idle()
} }
void DonateStrategy::stop() void DonateStrategy::suspend()
{ {
m_client->disconnect(); m_client->disconnect();
@@ -115,5 +122,5 @@ void DonateStrategy::onTimer(uv_timer_t *handle)
return strategy->connect(); return strategy->connect();
} }
strategy->stop(); strategy->suspend();
} }

View File

@@ -46,18 +46,19 @@ public:
inline bool isActive() const override { return m_active; } inline bool isActive() const override { return m_active; }
inline void resume() override {} inline void resume() override {}
int64_t submit(const JobResult &result) override;
void connect() override; void connect() override;
void submit(const JobResult &result) override; void stop() override;
protected: protected:
void onClose(Client *client, int failures) override; void onClose(Client *client, int failures) override;
void onJobReceived(Client *client, const Job &job) override; void onJobReceived(Client *client, const Job &job) override;
void onLoginSuccess(Client *client) override; void onLoginSuccess(Client *client) override;
void onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) override; void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) override;
private: private:
void idle(); void idle();
void stop(); void suspend();
static void onTimer(uv_timer_t *handle); static void onTimer(uv_timer_t *handle);

View File

@@ -39,6 +39,12 @@ FailoverStrategy::FailoverStrategy(const std::vector<Url*> &urls, const char *ag
} }
int64_t FailoverStrategy::submit(const JobResult &result)
{
return m_pools[m_active]->submit(result);
}
void FailoverStrategy::connect() void FailoverStrategy::connect()
{ {
m_pools[m_index]->connect(); m_pools[m_index]->connect();
@@ -55,9 +61,11 @@ void FailoverStrategy::resume()
} }
void FailoverStrategy::submit(const JobResult &result) void FailoverStrategy::stop()
{ {
m_pools[m_active]->submit(result); for (size_t i = 0; i < m_pools.size(); ++i) {
m_pools[i]->disconnect();
}
} }
@@ -111,9 +119,9 @@ void FailoverStrategy::onLoginSuccess(Client *client)
} }
void FailoverStrategy::onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) void FailoverStrategy::onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error)
{ {
m_listener->onResultAccepted(client, diff, ms, error); m_listener->onResultAccepted(client, seq, diff, ms, error);
} }

View File

@@ -45,15 +45,16 @@ public:
public: public:
inline bool isActive() const override { return m_active >= 0; } inline bool isActive() const override { return m_active >= 0; }
int64_t submit(const JobResult &result) override;
void connect() override; void connect() override;
void resume() override; void resume() override;
void submit(const JobResult &result) override; void stop() override;
protected: protected:
void onClose(Client *client, int failures) override; void onClose(Client *client, int failures) override;
void onJobReceived(Client *client, const Job &job) override; void onJobReceived(Client *client, const Job &job) override;
void onLoginSuccess(Client *client) override; void onLoginSuccess(Client *client) override;
void onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) override; void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) override;
private: private:
void add(const Url *url, const char *agent); void add(const Url *url, const char *agent);

View File

@@ -38,6 +38,12 @@ SinglePoolStrategy::SinglePoolStrategy(const Url *url, const char *agent, IStrat
} }
int64_t SinglePoolStrategy::submit(const JobResult &result)
{
return m_client->submit(result);
}
void SinglePoolStrategy::connect() void SinglePoolStrategy::connect()
{ {
m_client->connect(); m_client->connect();
@@ -54,9 +60,9 @@ void SinglePoolStrategy::resume()
} }
void SinglePoolStrategy::submit(const JobResult &result) void SinglePoolStrategy::stop()
{ {
m_client->submit(result); m_client->disconnect();
} }
@@ -84,7 +90,7 @@ void SinglePoolStrategy::onLoginSuccess(Client *client)
} }
void SinglePoolStrategy::onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) void SinglePoolStrategy::onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error)
{ {
m_listener->onResultAccepted(client, diff, ms, error); m_listener->onResultAccepted(client, seq, diff, ms, error);
} }

View File

@@ -42,15 +42,16 @@ public:
public: public:
inline bool isActive() const override { return m_active; } inline bool isActive() const override { return m_active; }
int64_t submit(const JobResult &result) override;
void connect() override; void connect() override;
void resume() override; void resume() override;
void submit(const JobResult &result) override; void stop() override;
protected: protected:
void onClose(Client *client, int failures) override; void onClose(Client *client, int failures) override;
void onJobReceived(Client *client, const Job &job) override; void onJobReceived(Client *client, const Job &job) override;
void onLoginSuccess(Client *client) override; void onLoginSuccess(Client *client) override;
void onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) override; void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) override;
private: private:
bool m_active; bool m_active;

View File

@@ -27,13 +27,13 @@
#define APP_ID "xmrig" #define APP_ID "xmrig"
#define APP_NAME "XMRig" #define APP_NAME "XMRig"
#define APP_DESC "Monero (XMR) CPU miner" #define APP_DESC "Monero (XMR) CPU miner"
#define APP_VERSION "2.0.0" #define APP_VERSION "2.1.0"
#define APP_DOMAIN "xmrig.com" #define APP_DOMAIN "xmrig.com"
#define APP_SITE "www.xmrig.com" #define APP_SITE "www.xmrig.com"
#define APP_COPYRIGHT "Copyright (C) 2016-2017 xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2017 xmrig.com"
#define APP_VER_MAJOR 2 #define APP_VER_MAJOR 2
#define APP_VER_MINOR 0 #define APP_VER_MINOR 1
#define APP_VER_BUILD 0 #define APP_VER_BUILD 0
#define APP_VER_REV 0 #define APP_VER_REV 0

View File

@@ -62,7 +62,7 @@ DoubleWorker::~DoubleWorker()
void DoubleWorker::start() void DoubleWorker::start()
{ {
while (true) { while (Workers::sequence() > 0) {
if (Workers::isPaused()) { if (Workers::isPaused()) {
do { do {
std::this_thread::sleep_for(std::chrono::milliseconds(200)); std::this_thread::sleep_for(std::chrono::milliseconds(200));
@@ -114,6 +114,9 @@ void DoubleWorker::consumeJob()
{ {
Job job = Workers::job(); Job job = Workers::job();
m_sequence = Workers::sequence(); m_sequence = Workers::sequence();
if (m_state->job == job) {
return;
}
save(job); save(job);

View File

@@ -34,6 +34,12 @@ Handle::Handle(int threadId, int threads, int64_t affinity) :
} }
void Handle::join()
{
uv_thread_join(&m_thread);
}
void Handle::start(void (*callback) (void *)) void Handle::start(void (*callback) (void *))
{ {
uv_thread_create(&m_thread, callback, this); uv_thread_create(&m_thread, callback, this);

View File

@@ -36,6 +36,7 @@ class Handle
{ {
public: public:
Handle(int threadId, int threads, int64_t affinity); Handle(int threadId, int threads, int64_t affinity);
void join();
void start(void (*callback) (void *)); void start(void (*callback) (void *));
inline int threadId() const { return m_threadId; } inline int threadId() const { return m_threadId; }

View File

@@ -161,6 +161,12 @@ void Hashrate::print()
} }
void Hashrate::stop()
{
uv_timer_stop(&m_timer);
}
void Hashrate::updateHighest() void Hashrate::updateHighest()
{ {
double highest = calc(2500); double highest = calc(2500);

View File

@@ -37,6 +37,7 @@ public:
double calc(size_t threadId, size_t ms) const; double calc(size_t threadId, size_t ms) const;
void add(size_t threadId, uint64_t count, uint64_t timestamp); void add(size_t threadId, uint64_t count, uint64_t timestamp);
void print(); void print();
void stop();
void updateHighest(); void updateHighest();
inline double highest() const { return m_highest; } inline double highest() const { return m_highest; }

View File

@@ -38,7 +38,7 @@ SingleWorker::SingleWorker(Handle *handle)
void SingleWorker::start() void SingleWorker::start()
{ {
while (true) { while (Workers::sequence() > 0) {
if (Workers::isPaused()) { if (Workers::isPaused()) {
do { do {
std::this_thread::sleep_for(std::chrono::milliseconds(200)); std::this_thread::sleep_for(std::chrono::milliseconds(200));
@@ -85,6 +85,9 @@ void SingleWorker::consumeJob()
{ {
Job job = Workers::job(); Job job = Workers::job();
m_sequence = Workers::sequence(); m_sequence = Workers::sequence();
if (m_job == job) {
return;
}
save(job); save(job);

View File

@@ -34,6 +34,8 @@
#include "workers/Workers.h" #include "workers/Workers.h"
bool Workers::m_active = false;
bool Workers::m_enabled = true;
Hashrate *Workers::m_hashrate = nullptr; Hashrate *Workers::m_hashrate = nullptr;
IJobResultListener *Workers::m_listener = nullptr; IJobResultListener *Workers::m_listener = nullptr;
Job Workers::m_job; Job Workers::m_job;
@@ -58,12 +60,33 @@ Job Workers::job()
} }
void Workers::setEnabled(bool enabled)
{
if (m_enabled == enabled) {
return;
}
m_enabled = enabled;
if (!m_active) {
return;
}
m_paused = enabled ? 0 : 1;
m_sequence++;
}
void Workers::setJob(const Job &job) void Workers::setJob(const Job &job)
{ {
uv_rwlock_wrlock(&m_rwlock); uv_rwlock_wrlock(&m_rwlock);
m_job = job; m_job = job;
uv_rwlock_wrunlock(&m_rwlock); uv_rwlock_wrunlock(&m_rwlock);
m_active = true;
if (!m_enabled) {
return;
}
m_sequence++; m_sequence++;
m_paused = 0; m_paused = 0;
} }
@@ -77,7 +100,7 @@ void Workers::start(int64_t affinity)
uv_mutex_init(&m_mutex); uv_mutex_init(&m_mutex);
uv_rwlock_init(&m_rwlock); uv_rwlock_init(&m_rwlock);
m_sequence = 0; m_sequence = 1;
m_paused = 1; m_paused = 1;
uv_async_init(uv_default_loop(), &m_async, Workers::onResult); uv_async_init(uv_default_loop(), &m_async, Workers::onResult);
@@ -92,6 +115,20 @@ void Workers::start(int64_t affinity)
} }
void Workers::stop()
{
uv_timer_stop(&m_timer);
m_hashrate->stop();
uv_close(reinterpret_cast<uv_handle_t*>(&m_async), nullptr);
m_sequence = 0;
for (size_t i = 0; i < m_workers.size(); ++i) {
m_workers[i]->join();
}
}
void Workers::submit(const JobResult &result) void Workers::submit(const JobResult &result)
{ {
uv_mutex_lock(&m_mutex); uv_mutex_lock(&m_mutex);

View File

@@ -43,14 +43,17 @@ class Workers
{ {
public: public:
static Job job(); static Job job();
static void setEnabled(bool enabled);
static void setJob(const Job &job); static void setJob(const Job &job);
static void start(int64_t affinity); static void start(int64_t affinity);
static void stop();
static void submit(const JobResult &result); static void submit(const JobResult &result);
static inline bool isEnabled() { return m_enabled; }
static inline bool isOutdated(uint64_t sequence) { return m_sequence.load(std::memory_order_relaxed) != sequence; } static inline bool isOutdated(uint64_t sequence) { return m_sequence.load(std::memory_order_relaxed) != sequence; }
static inline bool isPaused() { return m_paused.load(std::memory_order_relaxed) == 1; } static inline bool isPaused() { return m_paused.load(std::memory_order_relaxed) == 1; }
static inline uint64_t sequence() { return m_sequence.load(std::memory_order_relaxed); } static inline uint64_t sequence() { return m_sequence.load(std::memory_order_relaxed); }
static inline void pause() { m_paused = 1; m_sequence++; } static inline void pause() { m_active = false; m_paused = 1; m_sequence++; }
static inline void setListener(IJobResultListener *listener) { m_listener = listener; } static inline void setListener(IJobResultListener *listener) { m_listener = listener; }
private: private:
@@ -58,6 +61,8 @@ private:
static void onResult(uv_async_t *handle); static void onResult(uv_async_t *handle);
static void onTick(uv_timer_t *handle); static void onTick(uv_timer_t *handle);
static bool m_active;
static bool m_enabled;
static Hashrate *m_hashrate; static Hashrate *m_hashrate;
static IJobResultListener *m_listener; static IJobResultListener *m_listener;
static Job m_job; static Job m_job;

View File

@@ -25,7 +25,7 @@
int main(int argc, char **argv) { int main(int argc, char **argv) {
auto app = new App(argc, argv); App app(argc, argv);
return app->exec(); return app.exec();
} }