1
0
mirror of https://github.com/xmrig/xmrig.git synced 2025-12-06 23:52:38 -05:00

Compare commits

...

44 Commits

Author SHA1 Message Date
xmrig
4545c84a11 Update CHANGELOG.md 2017-07-06 10:05:36 +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
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
XMRig
32e7041def Fix possibility duplicate share for short donation intervals. 2017-07-03 03:34:23 +03:00
XMRig
c16388ade3 Fix possibility crash 2017-07-02 23:35:06 +03:00
xmrig
72569a7fc7 Update README.md 2017-07-02 22:21:29 +03:00
XMRig
751be470b8 Merge branch 'dev'
# Conflicts:
#	options.c
#	src/version.h
2017-07-02 22:16:23 +03:00
XMRig
7937c814ff v2.0.0 rc 2017-07-02 21:49:56 +03:00
xmrig
8e42fb9138 Update CHANGELOG.md 2017-07-02 07:36:24 +03:00
xmrig
dbc6f26c91 Update CHANGELOG.md 2017-07-02 07:34:02 +03:00
XMRig
074db6bb72 Add nice messages for accepted and rejected shares with diff and latency. 2017-07-02 05:33:10 +03:00
XMRig
71522214ae Show resolved pool ip. 2017-07-02 01:36:33 +03:00
XMRig
8ec58a8394 Fix nicehash support, please note --nicehash option now specified per pool. 2017-07-01 22:37:27 +03:00
XMRig
263634f585 Increase major version because --backup-url option removed and added ability to specify multiple pool urls. 2017-07-01 22:14:44 +03:00
XMRig
a383eba8df Merge branch 'feature-multiple-pools' into dev
# Conflicts:
#	src/Options.cpp
2017-07-01 21:50:27 +03:00
XMRig
152b65b67c Increase response timeout to 20 seconds. 2017-07-01 21:11:41 +03:00
XMRig
970b5d1964 Add FailoverStrategy. 2017-07-01 20:53:42 +03:00
XMRig
7536663caf Remove option --backup-url. 2017-06-30 13:23:13 +03:00
XMRig
7e17f77c11 Implemented DonateStrategy. 2017-06-30 03:20:50 +03:00
XMRig
25faeabd61 Implemented SinglePoolStrategy. 2017-06-29 01:48:23 +03:00
XMRig
bd8776b7ee Add classes SinglePoolStrategy, DonateStrategy, IStrategy, IStrategyListener. 2017-06-28 06:17:02 +03:00
XMRig
b2d26eb019 Use Url inside Client. Remove onLoginCredentialsRequired from IClientListener interface. 2017-06-28 04:04:04 +03:00
XMRig
14c6f8699e Fix --cpu-affinity overflow, again. 2017-06-27 18:47:33 +03:00
XMRig
c0dcfc2a97 Initial multiple pools support [2/2]. 2017-06-27 06:32:17 +03:00
XMRig
f36b5eeaad Fix --cpu-affinity overflow. 2017-06-26 23:08:10 +03:00
XMRig
952017ae7a Initial multiple pools support [1/2]. 2017-06-26 21:13:05 +03:00
XMRig
faf793b0aa Add syslog support. 2017-06-25 02:04:59 +03:00
XMRig
e97cd98f90 Fix file log for linux. 2017-06-23 19:37:41 +03:00
XMRig
95002ead7d Merge branch 'dev' of https://github.com/xmrig/xmrig into dev 2017-06-23 12:58:56 +03:00
XMRig
c1b3802590 Add option "-l, --log-file=FILE" and stub for option "-S, --syslog". 2017-06-23 03:12:46 +03:00
XMRig
1bfbc97c7d Add FileLog class. 2017-06-23 01:38:47 +03:00
XMRig
052290d0e9 Add ConsoleLog class and ILogBackend interface. 2017-06-22 14:41:34 +03:00
XMRig
4f512c41d4 Fix linux build 2017-06-22 02:30:26 +03:00
XMRig
91ed7e36cd Temporary disable TCP keepalive for Windows, fixes Windows XP support. 2017-06-21 21:40:15 +03:00
XMRig
77d9beaf89 Rename Console class to Log. 2017-06-20 13:04:38 +03:00
XMRig
a791bc113e Adjust console output. 2017-06-20 00:55:55 +03:00
XMRig
9bfa49b7d0 Fix regression, option --no-color not fully disabled colored output. 2017-06-19 10:58:28 +03:00
XMRig
ed0972da85 Update version. 2017-06-17 15:37:33 +03:00
xmrig
815f8cbb96 Update CHANGELOG.md 2017-06-17 15:34:42 +03:00
XMRig
ccc7fba2c4 Fix software AES. 2017-06-17 15:23:25 +03:00
XMRig
9dc02fc7f3 Fix for -a cryptonight-light. 2017-06-06 03:34:49 +03:00
XMRig
6551818610 Update libjansson to 2.10. 2017-06-06 03:31:44 +03:00
56 changed files with 1792 additions and 524 deletions

View File

@@ -1,3 +1,19 @@
# v2.0.1
- [#27](https://github.com/xmrig/xmrig/issues/27) Fixed possibility crash on 32bit systems.
# 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`
- [#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 `-S, --syslog` to use syslog for logging, Linux only.
- [#18](https://github.com/xmrig/xmrig/issues/18) Added nice messages for accepted/rejected shares with diff and network latency.
- [#20](https://github.com/xmrig/xmrig/issues/20) Fixed `--cpu-affinity` for more than 32 threads.
- Fixed Windows XP support.
- Fixed regression, option `--no-color` was not fully disable colored output.
- Show resolved pool IP address in miner output.
# v1.0.1
- Fix broken software AES implementation, app has crashed if CPU not support AES-NI, only version 1.0.0 affected.
# v1.0.0 # v1.0.0
- Miner complete rewritten in C++ with libuv. - Miner complete rewritten in C++ with libuv.
- This version should be fully compatible (except config file) with previos versions, many new nice features will come in next versions. - This version should be fully compatible (except config file) with previos versions, many new nice features will come in next versions.

View File

@@ -4,20 +4,33 @@ project(xmrig)
option(WITH_LIBCPUID "Use Libcpuid" ON) option(WITH_LIBCPUID "Use Libcpuid" ON)
option(WITH_AEON "CryptoNight-Lite support" ON) option(WITH_AEON "CryptoNight-Lite support" ON)
include (CheckIncludeFile)
set(HEADERS set(HEADERS
src/3rdparty/align.h src/3rdparty/align.h
src/App.h src/App.h
src/Console.h
src/Cpu.h src/Cpu.h
src/interfaces/IClientListener.h src/interfaces/IClientListener.h
src/interfaces/IJobResultListener.h src/interfaces/IJobResultListener.h
src/interfaces/ILogBackend.h
src/interfaces/IStrategy.h
src/interfaces/IStrategyListener.h
src/interfaces/IWorker.h src/interfaces/IWorker.h
src/log/ConsoleLog.h
src/log/FileLog.h
src/log/Log.h
src/Mem.h src/Mem.h
src/net/Client.h src/net/Client.h
src/net/Job.h src/net/Job.h
src/net/JobResult.h src/net/JobResult.h
src/net/Network.h src/net/Network.h
src/net/SubmitResult.h
src/net/Url.h src/net/Url.h
src/net/strategies/DonateStrategy.h
src/net/strategies/FailoverStrategy.h
src/net/strategies/SinglePoolStrategy.h
src/Options.h src/Options.h
src/Summary.h src/Summary.h
src/version.h src/version.h
@@ -45,12 +58,17 @@ set(HEADERS_CRYPTO
set(SOURCES set(SOURCES
src/App.cpp src/App.cpp
src/Console.cpp src/log/ConsoleLog.cpp
src/log/FileLog.cpp
src/log/Log.cpp
src/Mem.cpp src/Mem.cpp
src/net/Client.cpp src/net/Client.cpp
src/net/Job.cpp src/net/Job.cpp
src/net/Network.cpp src/net/Network.cpp
src/net/Url.cpp src/net/Url.cpp
src/net/strategies/DonateStrategy.cpp
src/net/strategies/FailoverStrategy.cpp
src/net/strategies/SinglePoolStrategy.cpp
src/Options.cpp src/Options.cpp
src/Summary.cpp src/Summary.cpp
src/workers/DoubleWorker.cpp src/workers/DoubleWorker.cpp
@@ -119,7 +137,7 @@ endif()
# https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_ID.html # https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_ID.html
if (CMAKE_CXX_COMPILER_ID MATCHES GNU) if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes -Wall -Wno-strict-aliasing")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -std=c++14 -fno-exceptions -fno-rtti") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes -Wall -std=c++14 -fno-exceptions -fno-rtti")
@@ -161,6 +179,12 @@ else()
set(SOURCES_CPUID src/Cpu_stub.cpp) set(SOURCES_CPUID src/Cpu_stub.cpp)
endif() endif()
CHECK_INCLUDE_FILE (syslog.h HAVE_SYSLOG_H)
if (HAVE_SYSLOG_H)
add_definitions(/DHAVE_SYSLOG_H)
set(SOURCES_SYSLOG src/log/SysLog.h src/log/SysLog.cpp)
endif()
include_directories(src) include_directories(src)
include_directories(src/3rdparty) include_directories(src/3rdparty)
include_directories(src/3rdparty/jansson) include_directories(src/3rdparty/jansson)
@@ -168,5 +192,5 @@ include_directories(${UV_INCLUDE_DIR})
add_subdirectory(src/3rdparty/jansson) add_subdirectory(src/3rdparty/jansson)
add_executable(xmrig ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO}) add_executable(xmrig ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG})
target_link_libraries(xmrig jansson ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB}) target_link_libraries(xmrig jansson ${UV_LIBRARIES} ${EXTRA_LIBS} ${CPUID_LIB})

View File

@@ -2,7 +2,7 @@
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. Based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of legacy code.
<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)
@@ -38,11 +38,16 @@ Based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of
xmrig.exe -o xmr-eu.dwarfpool.com:8005 -u YOUR_WALLET -p x -k xmrig.exe -o xmr-eu.dwarfpool.com:8005 -u YOUR_WALLET -p x -k
``` ```
### Failover
```
xmrig.exe -o pool.supportxmr.com:5555 -u YOUR_WALLET1 -k -o xmr-eu.dwarfpool.com:8005 -u YOUR_WALLET2 -p x -k
```
For failover you can add multiple pools, maximum count not limited.
### Options ### Options
``` ```
-a, --algo=ALGO cryptonight (default) or cryptonight-lite -a, --algo=ALGO cryptonight (default) or cryptonight-lite
-o, --url=URL URL of mining server -o, --url=URL URL of mining server
-b, --backup-url=URL URL of backup mining server
-O, --userpass=U:P username:password pair for mining server -O, --userpass=U:P username:password pair for mining server
-u, --user=USERNAME username for mining server -u, --user=USERNAME username for mining server
-p, --pass=PASSWORD password for mining server -p, --pass=PASSWORD password for mining server

View File

@@ -27,9 +27,11 @@
#include "App.h" #include "App.h"
#include "Console.h"
#include "Cpu.h" #include "Cpu.h"
#include "crypto/CryptoNight.h" #include "crypto/CryptoNight.h"
#include "log/ConsoleLog.h"
#include "log/FileLog.h"
#include "log/Log.h"
#include "Mem.h" #include "Mem.h"
#include "net/Network.h" #include "net/Network.h"
#include "Options.h" #include "Options.h"
@@ -38,6 +40,11 @@
#include "workers/Workers.h" #include "workers/Workers.h"
#ifdef HAVE_SYSLOG_H
# include "log/SysLog.h"
#endif
App *App::m_self = nullptr; App *App::m_self = nullptr;
@@ -48,10 +55,25 @@ App::App(int argc, char **argv) :
{ {
m_self = this; m_self = this;
Console::init();
Cpu::init(); Cpu::init();
m_options = Options::parse(argc, argv); m_options = Options::parse(argc, argv);
Log::init();
if (!m_options->background()) {
Log::add(new ConsoleLog(m_options->colors()));
}
if (m_options->logFile()) {
Log::add(new FileLog(m_options->logFile()));
}
# ifdef HAVE_SYSLOG_H
if (m_options->syslog()) {
Log::add(new SysLog());
}
# endif
m_network = new Network(m_options); m_network = new Network(m_options);
uv_signal_init(uv_default_loop(), &m_signal); uv_signal_init(uv_default_loop(), &m_signal);
@@ -69,21 +91,21 @@ int App::exec()
return 0; return 0;
} }
if (!CryptoNight::init(m_options->algo(), m_options->algoVariant())) {
LOG_ERR("\"%s\" hash self-test failed.", m_options->algoName());
return 1;
}
uv_signal_start(&m_signal, App::onSignal, SIGHUP); uv_signal_start(&m_signal, App::onSignal, SIGHUP);
uv_signal_start(&m_signal, App::onSignal, SIGTERM); uv_signal_start(&m_signal, App::onSignal, SIGTERM);
uv_signal_start(&m_signal, App::onSignal, SIGINT); uv_signal_start(&m_signal, App::onSignal, SIGINT);
background(); background();
if (!CryptoNight::init(m_options->algo(), m_options->algoVariant())) {
LOG_ERR("\"%s\" hash self-test failed.", m_options->algoName());
return 1;
}
Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash()); Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash());
Summary::print(); Summary::print();
Workers::start(m_options->affinity(), m_options->nicehash()); Workers::start(m_options->affinity());
m_network->connect(); m_network->connect();

View File

@@ -29,8 +29,8 @@
#include "App.h" #include "App.h"
#include "Console.h"
#include "Cpu.h" #include "Cpu.h"
#include "log/Log.h"
#include "Options.h" #include "Options.h"

View File

@@ -25,6 +25,9 @@
#define __CPU_H__ #define __CPU_H__
#include <stdint.h>
class Cpu class Cpu
{ {
public: public:
@@ -36,7 +39,7 @@ public:
static int optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage); static int optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage);
static void init(); static void init();
static void setAffinity(int id, unsigned long mask); static void setAffinity(int id, uint64_t mask);
static inline bool hasAES() { return m_flags & AES; } static inline bool hasAES() { return m_flags & AES; }
static inline bool isX64() { return m_flags & X86_64; } static inline bool isX64() { return m_flags & X86_64; }

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

@@ -40,7 +40,7 @@ void Cpu::init()
} }
void Cpu::setAffinity(int id, unsigned long mask) void Cpu::setAffinity(int id, uint64_t mask)
{ {
cpu_set_t set; cpu_set_t set;
CPU_ZERO(&set); CPU_ZERO(&set);

View File

@@ -41,7 +41,7 @@ void Cpu::init()
} }
void Cpu::setAffinity(int id, unsigned long mask) void Cpu::setAffinity(int id, uint64_t mask)
{ {
if (id == -1) { if (id == -1) {
SetProcessAffinityMask(GetCurrentProcess(), mask); SetProcessAffinityMask(GetCurrentProcess(), mask);

View File

@@ -25,6 +25,7 @@
#define __MEM_H__ #define __MEM_H__
#include <stddef.h>
#include <stdint.h> #include <stdint.h>

View File

@@ -28,9 +28,9 @@
#include "crypto/CryptoNight.h" #include "crypto/CryptoNight.h"
#include "log/Log.h"
#include "Mem.h" #include "Mem.h"
#include "Options.h" #include "Options.h"
#include "Console.h"
bool Mem::allocate(int algo, int threads, bool doubleHash) bool Mem::allocate(int algo, int threads, bool doubleHash)

View File

@@ -33,7 +33,7 @@
# include <malloc.h> # include <malloc.h>
#endif #endif
#include "Console.h" #include "log/Log.h"
#include "crypto/CryptoNight.h" #include "crypto/CryptoNight.h"
#include "Mem.h" #include "Mem.h"
#include "Options.h" #include "Options.h"

View File

@@ -34,7 +34,6 @@
#endif #endif
#include "Console.h"
#include "Cpu.h" #include "Cpu.h"
#include "donate.h" #include "donate.h"
#include "net/Url.h" #include "net/Url.h"
@@ -55,7 +54,6 @@ Usage: " APP_ID " [OPTIONS]\n\
Options:\n\ Options:\n\
-a, --algo=ALGO cryptonight (default) or cryptonight-lite\n\ -a, --algo=ALGO cryptonight (default) or cryptonight-lite\n\
-o, --url=URL URL of mining server\n\ -o, --url=URL URL of mining server\n\
-b, --backup-url=URL URL of backup mining server\n\
-O, --userpass=U:P username:password pair for mining server\n\ -O, --userpass=U:P username:password pair for mining server\n\
-u, --user=USERNAME username for mining server\n\ -u, --user=USERNAME username for mining server\n\
-p, --pass=PASSWORD password for mining server\n\ -p, --pass=PASSWORD password for mining server\n\
@@ -69,6 +67,12 @@ Options:\n\
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\ --donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\
-B, --background run the miner in the background\n\ -B, --background run the miner in the background\n\
-c, --config=FILE load a JSON-format configuration file\n\ -c, --config=FILE load a JSON-format configuration file\n\
-l, --log-file=FILE log all output to a file\n"
# ifdef HAVE_SYSLOG_H
"\
-S, --syslog use system log for output messages\n"
# endif
"\
--max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)\n\ --max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)\n\
--safe safe adjust threads and av settings for current CPU\n\ --safe safe adjust threads and av settings for current CPU\n\
--nicehash enable nicehash support\n\ --nicehash enable nicehash support\n\
@@ -78,19 +82,19 @@ Options:\n\
"; ";
static char const short_options[] = "a:c:khBp:Px:r:R:s:t:T:o:u:O:v:Vb:"; static char const short_options[] = "a:c:khBp:Px:r:R:s:t:T:o:u:O:v:Vl:S";
static struct option const options[] = { static struct option const options[] = {
{ "algo", 1, nullptr, 'a' }, { "algo", 1, nullptr, 'a' },
{ "av", 1, nullptr, 'v' }, { "av", 1, nullptr, 'v' },
{ "background", 0, nullptr, 'B' }, { "background", 0, nullptr, 'B' },
{ "backup-url", 1, nullptr, 'b' },
{ "config", 1, nullptr, 'c' }, { "config", 1, nullptr, 'c' },
{ "cpu-affinity", 1, nullptr, 1020 }, { "cpu-affinity", 1, nullptr, 1020 },
{ "donate-level", 1, nullptr, 1003 }, { "donate-level", 1, nullptr, 1003 },
{ "help", 0, nullptr, 'h' }, { "help", 0, nullptr, 'h' },
{ "keepalive", 0, nullptr ,'k' }, { "keepalive", 0, nullptr ,'k' },
{ "log-file", 1, nullptr, 'l' },
{ "max-cpu-usage", 1, nullptr, 1004 }, { "max-cpu-usage", 1, nullptr, 1004 },
{ "nicehash", 0, nullptr, 1006 }, { "nicehash", 0, nullptr, 1006 },
{ "no-color", 0, nullptr, 1002 }, { "no-color", 0, nullptr, 1002 },
@@ -99,6 +103,7 @@ static struct option const options[] = {
{ "retries", 1, nullptr, 'r' }, { "retries", 1, nullptr, 'r' },
{ "retry-pause", 1, nullptr, 'R' }, { "retry-pause", 1, nullptr, 'R' },
{ "safe", 0, nullptr, 1005 }, { "safe", 0, nullptr, 1005 },
{ "syslog", 0, nullptr, 'S' },
{ "threads", 1, nullptr, 't' }, { "threads", 1, nullptr, 't' },
{ "url", 1, nullptr, 'o' }, { "url", 1, nullptr, 'o' },
{ "user", 1, nullptr, 'u' }, { "user", 1, nullptr, 'u' },
@@ -136,12 +141,10 @@ Options::Options(int argc, char **argv) :
m_background(false), m_background(false),
m_colors(true), m_colors(true),
m_doubleHash(false), m_doubleHash(false),
m_keepAlive(false),
m_nicehash(false),
m_ready(false), m_ready(false),
m_safe(false), m_safe(false),
m_pass(nullptr), m_syslog(false),
m_user(nullptr), m_logFile(nullptr),
m_algo(0), m_algo(0),
m_algoVariant(0), m_algoVariant(0),
m_donateLevel(kDonateLevel), m_donateLevel(kDonateLevel),
@@ -150,10 +153,10 @@ Options::Options(int argc, char **argv) :
m_retries(5), m_retries(5),
m_retryPause(5), m_retryPause(5),
m_threads(0), m_threads(0),
m_affinity(-1L), m_affinity(-1L)
m_backupUrl(nullptr),
m_url(nullptr)
{ {
m_pools.push_back(new Url());
int key; int key;
while (1) { while (1) {
@@ -172,23 +175,11 @@ Options::Options(int argc, char **argv) :
return; return;
} }
if (!m_url) { if (!m_pools[0]->isValid()) {
LOG_ERR("No pool URL supplied. Exiting.", argv[0]); fprintf(stderr, "No pool URL supplied. Exiting.");
return; return;
} }
if (!m_nicehash && m_url->isNicehash()) {
m_nicehash = true;
}
if (!m_user) {
m_user = strdup("x");
}
if (!m_pass) {
m_pass = strdup("x");
}
m_algoVariant = getAlgoVariant(); m_algoVariant = getAlgoVariant();
if (m_algoVariant == AV2_AESNI_DOUBLE || m_algoVariant == AV4_SOFT_AES_DOUBLE) { if (m_algoVariant == AV2_AESNI_DOUBLE || m_algoVariant == AV4_SOFT_AES_DOUBLE) {
m_doubleHash = true; m_doubleHash = true;
@@ -210,11 +201,6 @@ Options::Options(int argc, char **argv) :
Options::~Options() Options::~Options()
{ {
delete m_url;
delete m_backupUrl;
free(m_user);
free(m_pass);
} }
@@ -222,8 +208,6 @@ bool Options::parseArg(int key, char *arg)
{ {
char *p; char *p;
int v; int v;
uint64_t ul;
Url *url;
switch (key) { switch (key) {
case 'a': /* --algo */ case 'a': /* --algo */
@@ -233,35 +217,44 @@ bool Options::parseArg(int key, char *arg)
break; break;
case 'O': /* --userpass */ case 'O': /* --userpass */
if (!setUserpass(arg)) { if (!m_pools.back()->setUserpass(arg)) {
return false; return false;
} }
break; break;
case 'o': /* --url */ case 'o': /* --url */
url = parseUrl(arg); if (m_pools.size() > 1 || m_pools[0]->isValid()) {
if (url) { Url *url = new Url(arg);
free(m_url); if (url->isValid()) {
m_url = url; m_pools.push_back(url);
}
else {
delete url;
}
}
else {
m_pools[0]->parse(arg);
} }
break;
case 'b': /* --backup-url */ if (!m_pools.back()->isValid()) {
url = parseUrl(arg); return false;
if (url) {
free(m_backupUrl);
m_backupUrl = url;
} }
break; break;
case 'u': /* --user */ case 'u': /* --user */
free(m_user); m_pools.back()->setUser(arg);
m_user = strdup(arg);
break; break;
case 'p': /* --pass */ case 'p': /* --pass */
free(m_pass); m_pools.back()->setPassword(arg);
m_pass = strdup(arg); break;
case 'l': /* --log-file */
free(m_logFile);
m_logFile = strdup(arg);
m_colors = false;
break; break;
case 'r': /* --retries */ case 'r': /* --retries */
@@ -309,7 +302,7 @@ bool Options::parseArg(int key, char *arg)
break; break;
case 'k': /* --keepalive */ case 'k': /* --keepalive */
m_keepAlive = true; m_pools.back()->setKeepAlive(true);
break; break;
case 'V': /* --version */ case 'V': /* --version */
@@ -325,6 +318,11 @@ bool Options::parseArg(int key, char *arg)
m_colors = false; m_colors = false;
break; break;
case 'S': /* --syslog */
m_syslog = true;
m_colors = false;
break;
case 'v': /* --av */ case 'v': /* --av */
v = strtol(arg, nullptr, 10); v = strtol(arg, nullptr, 10);
if (v < 0 || v > 1000) { if (v < 0 || v > 1000) {
@@ -337,12 +335,7 @@ bool Options::parseArg(int key, char *arg)
case 1020: /* --cpu-affinity */ case 1020: /* --cpu-affinity */
p = strstr(arg, "0x"); p = strstr(arg, "0x");
ul = p ? strtoul(p, NULL, 16) : atol(arg); m_affinity = p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10);
if (ul > (1UL << Cpu::threads()) -1) {
ul = -1;
}
m_affinity = ul;
break; break;
case 1002: /* --no-color */ case 1002: /* --no-color */
@@ -360,7 +353,7 @@ bool Options::parseArg(int key, char *arg)
break; break;
case 1006: /* --nicehash */ case 1006: /* --nicehash */
m_nicehash = true; m_pools.back()->setNicehash(true);
break; break;
case 1007: /* --print-time */ case 1007: /* --print-time */
@@ -463,25 +456,6 @@ bool Options::setAlgo(const char *algo)
} }
bool Options::setUserpass(const char *userpass)
{
const char *p = strchr(userpass, ':');
if (!p) {
showUsage(1);
return false;
}
free(m_user);
free(m_pass);
m_user = static_cast<char*>(calloc(p - userpass + 1, 1));
strncpy(m_user, userpass, p - userpass);
m_pass = strdup(p + 1);
return true;
}
int Options::getAlgoVariant() const int Options::getAlgoVariant() const
{ {
# ifndef XMRIG_NO_AEON # ifndef XMRIG_NO_AEON

View File

@@ -25,6 +25,7 @@
#define __OPTIONS_H__ #define __OPTIONS_H__
#include <vector>
#include <stdint.h> #include <stdint.h>
@@ -51,24 +52,21 @@ public:
static inline Options* i() { return m_self; } static inline Options* i() { return m_self; }
static Options *parse(int argc, char **argv); static Options *parse(int argc, char **argv);
inline bool background() const { return m_background; } inline bool background() const { return m_background; }
inline bool colors() const { return m_colors; } inline bool colors() const { return m_colors; }
inline bool doubleHash() const { return m_doubleHash; } inline bool doubleHash() const { return m_doubleHash; }
inline bool isReady() const { return m_ready; } inline bool isReady() const { return m_ready; }
inline bool keepAlive() const { return m_keepAlive; } inline bool syslog() const { return m_syslog; }
inline bool nicehash() const { return m_nicehash; } inline const char *logFile() const { return m_logFile; }
inline const char *pass() const { return m_pass; } inline const std::vector<Url*> &pools() const { return m_pools; }
inline const char *user() const { return m_user; } inline int algo() const { return m_algo; }
inline const Url *backupUrl() const { return m_backupUrl; } inline int algoVariant() const { return m_algoVariant; }
inline const Url *url() const { return m_url; } inline int donateLevel() const { return m_donateLevel; }
inline int algo() const { return m_algo; } inline int printTime() const { return m_printTime; }
inline int algoVariant() const { return m_algoVariant; } inline int retries() const { return m_retries; }
inline int donateLevel() const { return m_donateLevel; } inline int retryPause() const { return m_retryPause; }
inline int printTime() const { return m_printTime; } inline int threads() const { return m_threads; }
inline int retries() const { return m_retries; } inline int64_t affinity() const { return m_affinity; }
inline int retryPause() const { return m_retryPause; }
inline int threads() const { return m_threads; }
inline int64_t affinity() const { return m_affinity; }
const char *algoName() const; const char *algoName() const;
@@ -84,7 +82,6 @@ private:
void showVersion(void); void showVersion(void);
bool setAlgo(const char *algo); bool setAlgo(const char *algo);
bool setUserpass(const char *userpass);
int getAlgoVariant() const; int getAlgoVariant() const;
# ifndef XMRIG_NO_AEON # ifndef XMRIG_NO_AEON
@@ -94,12 +91,10 @@ private:
bool m_background; bool m_background;
bool m_colors; bool m_colors;
bool m_doubleHash; bool m_doubleHash;
bool m_keepAlive;
bool m_nicehash;
bool m_ready; bool m_ready;
bool m_safe; bool m_safe;
char *m_pass; bool m_syslog;
char *m_user; char *m_logFile;
int m_algo; int m_algo;
int m_algoVariant; int m_algoVariant;
int m_donateLevel; int m_donateLevel;
@@ -109,8 +104,7 @@ private:
int m_retryPause; int m_retryPause;
int m_threads; int m_threads;
int64_t m_affinity; int64_t m_affinity;
Url *m_backupUrl; std::vector<Url*> m_pools;
Url *m_url;
}; };
#endif /* __OPTIONS_H__ */ #endif /* __OPTIONS_H__ */

View File

@@ -25,8 +25,8 @@
#include <uv.h> #include <uv.h>
#include "Console.h"
#include "Cpu.h" #include "Cpu.h"
#include "log/Log.h"
#include "Mem.h" #include "Mem.h"
#include "net/Url.h" #include "net/Url.h"
#include "Options.h" #include "Options.h"
@@ -50,21 +50,21 @@ static void print_versions()
if (Options::i()->colors()) { if (Options::i()->colors()) {
Console::i()->text("\x1B[01;32m * \x1B[01;37mVERSIONS: \x1B[01;36mXMRig/%s\x1B[01;37m libuv/%s%s", APP_VERSION, uv_version_string(), buf); Log::i()->text("\x1B[01;32m * \x1B[01;37mVERSIONS: \x1B[01;36mXMRig/%s\x1B[01;37m libuv/%s%s", APP_VERSION, uv_version_string(), buf);
} else { } else {
Console::i()->text(" * VERSIONS: XMRig/%s libuv/%s%s", APP_VERSION, uv_version_string(), buf); Log::i()->text(" * VERSIONS: XMRig/%s libuv/%s%s", APP_VERSION, uv_version_string(), buf);
} }
} }
static void print_memory() { static void print_memory() {
if (Options::i()->colors()) { if (Options::i()->colors()) {
Console::i()->text("\x1B[01;32m * \x1B[01;37mHUGE PAGES: %s, %s", Log::i()->text("\x1B[01;32m * \x1B[01;37mHUGE PAGES: %s, %s",
Mem::isHugepagesAvailable() ? "\x1B[01;32mavailable" : "\x1B[01;31munavailable", Mem::isHugepagesAvailable() ? "\x1B[01;32mavailable" : "\x1B[01;31munavailable",
Mem::isHugepagesEnabled() ? "\x1B[01;32menabled" : "\x1B[01;31mdisabled"); Mem::isHugepagesEnabled() ? "\x1B[01;32menabled" : "\x1B[01;31mdisabled");
} }
else { else {
Console::i()->text(" * HUGE PAGES: %s, %s", Mem::isHugepagesAvailable() ? "available" : "unavailable", Mem::isHugepagesEnabled() ? "enabled" : "disabled"); Log::i()->text(" * HUGE PAGES: %s, %s", Mem::isHugepagesAvailable() ? "available" : "unavailable", Mem::isHugepagesEnabled() ? "enabled" : "disabled");
} }
} }
@@ -72,19 +72,19 @@ static void print_memory() {
static void print_cpu() static void print_cpu()
{ {
if (Options::i()->colors()) { if (Options::i()->colors()) {
Console::i()->text("\x1B[01;32m * \x1B[01;37mCPU: %s (%d) %sx64 %sAES-NI", Log::i()->text("\x1B[01;32m * \x1B[01;37mCPU: %s (%d) %sx64 %sAES-NI",
Cpu::brand(), Cpu::brand(),
Cpu::sockets(), Cpu::sockets(),
Cpu::isX64() ? "\x1B[01;32m" : "\x1B[01;31m-", Cpu::isX64() ? "\x1B[01;32m" : "\x1B[01;31m-",
Cpu::hasAES() ? "\x1B[01;32m" : "\x1B[01;31m-"); Cpu::hasAES() ? "\x1B[01;32m" : "\x1B[01;31m-");
# ifndef XMRIG_NO_LIBCPUID # ifndef XMRIG_NO_LIBCPUID
Console::i()->text("\x1B[01;32m * \x1B[01;37mCPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0); Log::i()->text("\x1B[01;32m * \x1B[01;37mCPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0);
# endif # endif
} }
else { else {
Console::i()->text(" * CPU: %s (%d) %sx64 %sAES-NI", Cpu::brand(), Cpu::sockets(), Cpu::isX64() ? "" : "-", Cpu::hasAES() ? "" : "-"); Log::i()->text(" * CPU: %s (%d) %sx64 %sAES-NI", Cpu::brand(), Cpu::sockets(), Cpu::isX64() ? "" : "-", Cpu::hasAES() ? "" : "-");
# ifndef XMRIG_NO_LIBCPUID # ifndef XMRIG_NO_LIBCPUID
Console::i()->text(" * CPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0); Log::i()->text(" * CPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0);
# endif # endif
} }
} }
@@ -100,28 +100,32 @@ static void print_threads()
buf[0] = '\0'; buf[0] = '\0';
} }
Console::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, donate=%d%%%s%s" : " * THREADS: %d, %s, av=%d, donate=%d%%%s%s", Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, %sdonate=%d%%%s" : " * THREADS: %d, %s, av=%d, %sdonate=%d%%%s",
Options::i()->threads(), Options::i()->threads(),
Options::i()->algoName(), Options::i()->algoName(),
Options::i()->algoVariant(), Options::i()->algoVariant(),
Options::i()->donateLevel(), Options::i()->colors() && Options::i()->donateLevel() == 0 ? "\x1B[01;31m" : "",
Options::i()->nicehash() ? ", nicehash" : "", buf); Options::i()->donateLevel(),
buf);
} }
static void print_pools() static void print_pools()
{ {
Console::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mPOOL #1: \x1B[01;36m%s:%d" : " * POOL #1: %s:%d", const std::vector<Url*> &pools = Options::i()->pools();
Options::i()->url()->host(),
Options::i()->url()->port());
if (!Options::i()->backupUrl()) { for (size_t i = 0; i < pools.size(); ++i) {
return; Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mPOOL #%d: \x1B[01;36m%s:%d" : " * POOL #%d: %s:%d",
i + 1,
pools[i]->host(),
pools[i]->port());
} }
Console::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mPOOL #2: \x1B[01;36m%s:%d" : " * POOL #2: %s:%d", # ifdef APP_DEBUG
Options::i()->backupUrl()->host(), for (size_t i = 0; i < pools.size(); ++i) {
Options::i()->backupUrl()->port()); Log::i()->text("%s:%d, user: %s, pass: %s, ka: %d, nicehash: %d", pools[i]->host(), pools[i]->port(), pools[i]->user(), pools[i]->password(), pools[i]->isKeepAlive(), pools[i]->isNicehash());
}
# endif
} }

View File

@@ -327,7 +327,13 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *
for (size_t i = 0; i < ITERATIONS; i++) { for (size_t i = 0; i < ITERATIONS; i++) {
__m128i cx; __m128i cx;
cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0));
if (SOFT_AES) {
cx = soft_aesenc(cx, _mm_set_epi64x(ah0, al0));
}
else {
cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0));
}
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
idx0 = EXTRACT64(cx); idx0 = EXTRACT64(cx);
@@ -385,8 +391,14 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size,
__m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); __m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
__m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]); __m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]);
cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0)); if (SOFT_AES) {
cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1)); cx0 = soft_aesenc(cx0, _mm_set_epi64x(ah0, al0));
cx1 = soft_aesenc(cx1, _mm_set_epi64x(ah1, al1));
}
else {
cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0));
cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1));
}
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
_mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); _mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));

View File

@@ -25,6 +25,9 @@
#define __ICLIENTLISTENER_H__ #define __ICLIENTLISTENER_H__
#include <stdint.h>
class Client; class Client;
class Job; class Job;
@@ -34,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 onLoginCredentialsRequired(Client *client) = 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;
}; };

View File

@@ -0,0 +1,41 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 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 __ILOGBACKEND_H__
#define __ILOGBACKEND_H__
#include <stdarg.h>
class ILogBackend
{
public:
virtual ~ILogBackend() {}
virtual void message(int level, const char* fmt, va_list args) = 0;
virtual void text(const char* fmt, va_list args) = 0;
};
#endif // __ILOGBACKEND_H__

View File

@@ -0,0 +1,43 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 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 __ISTRATEGY_H__
#define __ISTRATEGY_H__
class JobResult;
class IStrategy
{
public:
virtual ~IStrategy() {}
virtual bool isActive() const = 0;
virtual void connect() = 0;
virtual void resume() = 0;
virtual void submit(const JobResult &result) = 0;
};
#endif // __ISTRATEGY_H__

View File

@@ -0,0 +1,48 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 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 __ISTRATEGYLISTENER_H__
#define __ISTRATEGYLISTENER_H__
#include <stdint.h>
class Client;
class IStrategy;
class Job;
class IStrategyListener
{
public:
virtual ~IStrategyListener() {}
virtual void onActive(Client *client) = 0;
virtual void onJob(Client *client, const Job &job) = 0;
virtual void onPause(IStrategy *strategy) = 0;
virtual void onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) = 0;
};
#endif // __ISTRATEGYLISTENER_H__

View File

@@ -34,21 +34,17 @@
# include "3rdparty/winansi.h" # include "3rdparty/winansi.h"
#endif #endif
#include "Console.h" #include "log/ConsoleLog.h"
#include "log/Log.h"
Console *Console::m_self = nullptr; ConsoleLog::ConsoleLog(bool colors) :
m_colors(colors)
void Console::init()
{ {
if (!m_self) {
m_self = new Console();
}
} }
void Console::message(Console::Level level, const char* fmt, ...) void ConsoleLog::message(int level, const char* fmt, va_list args)
{ {
time_t now = time(nullptr); time_t now = time(nullptr);
tm stime; tm stime;
@@ -59,26 +55,23 @@ void Console::message(Console::Level level, const char* fmt, ...)
localtime_r(&now, &stime); localtime_r(&now, &stime);
# endif # endif
va_list ap;
va_start(ap, fmt);
const char* color = nullptr; const char* color = nullptr;
if (m_colors) { if (m_colors) {
switch (level) { switch (level) {
case ERR: case Log::ERR:
color = kCL_RED; color = Log::kCL_RED;
break; break;
case WARNING: case Log::WARNING:
color = kCL_YELLOW; color = Log::kCL_YELLOW;
break; break;
case NOTICE: case Log::NOTICE:
color = kCL_WHITE; color = Log::kCL_WHITE;
break; break;
case DEBUG: case Log::DEBUG:
color = kCL_GRAY; color = Log::kCL_GRAY;
break; break;
default: default:
@@ -97,48 +90,23 @@ void Console::message(Console::Level level, const char* fmt, ...)
stime.tm_hour, stime.tm_hour,
stime.tm_min, stime.tm_min,
stime.tm_sec, stime.tm_sec,
color, m_colors ? color : "",
fmt, fmt,
m_colors ? kCL_N : "" m_colors ? Log::kCL_N : ""
); );
uv_mutex_lock(&m_mutex); vfprintf(stdout, buf, args);
vfprintf(stdout, buf, ap);
fflush(stdout); fflush(stdout);
uv_mutex_unlock(&m_mutex);
va_end(ap);
} }
void Console::text(const char* fmt, ...) void ConsoleLog::text(const char* fmt, va_list args)
{ {
va_list ap;
va_start(ap, fmt);
const int len = 64 + strlen(fmt) + 2; const int len = 64 + strlen(fmt) + 2;
char *buf = static_cast<char *>(alloca(len)); char *buf = static_cast<char *>(alloca(len));
sprintf(buf, "%s%s\n", sprintf(buf, "%s%s\n", fmt, m_colors ? Log::kCL_N : "");
fmt,
m_colors ? kCL_N : ""
);
uv_mutex_lock(&m_mutex); vfprintf(stdout, buf, args);
vfprintf(stdout, buf, ap);
fflush(stdout); fflush(stdout);
uv_mutex_unlock(&m_mutex);
va_end(ap);
}
Console::Console() :
m_colors(true)
{
uv_mutex_init(&m_mutex);
} }

43
src/log/ConsoleLog.h Normal file
View File

@@ -0,0 +1,43 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 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 __CONSOLELOG_H__
#define __CONSOLELOG_H__
#include "interfaces/ILogBackend.h"
class ConsoleLog : public ILogBackend
{
public:
ConsoleLog(bool colors);
void message(int level, const char* fmt, va_list args) override;
void text(const char* fmt, va_list args) override;
private:
bool m_colors;
};
#endif /* __CONSOLELOG_H__ */

103
src/log/FileLog.cpp Normal file
View File

@@ -0,0 +1,103 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 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 <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef WIN32
# include <winsock2.h>
# include <malloc.h>
# include "3rdparty/winansi.h"
#endif
#include "log/FileLog.h"
FileLog::FileLog(const char *fileName)
{
uv_fs_t req;
m_file = uv_fs_open(uv_default_loop(), &req, fileName, O_CREAT | O_APPEND | O_WRONLY, 0644, nullptr);
uv_fs_req_cleanup(&req);
}
void FileLog::message(int level, const char* fmt, va_list args)
{
if (m_file < 0) {
return;
}
time_t now = time(nullptr);
tm stime;
# ifdef _WIN32
localtime_s(&stime, &now);
# else
localtime_r(&now, &stime);
# endif
char *buf = static_cast<char*>(malloc(512));
int size = snprintf(buf, 23, "[%d-%02d-%02d %02d:%02d:%02d] ",
stime.tm_year + 1900,
stime.tm_mon + 1,
stime.tm_mday,
stime.tm_hour,
stime.tm_min,
stime.tm_sec);
size = vsnprintf(buf + size, 512 - size - 1, fmt, args) + size;
buf[size] = '\n';
write(buf, size + 1);
}
void FileLog::text(const char* fmt, va_list args)
{
message(0, fmt, args);
}
void FileLog::onWrite(uv_fs_t *req)
{
free(req->data);
uv_fs_req_cleanup(req);
free(req);
}
void FileLog::write(char *data, size_t size)
{
uv_buf_t buf = uv_buf_init(data, size);
uv_fs_t *req = static_cast<uv_fs_t*>(malloc(sizeof(uv_fs_t)));
req->data = buf.base;
uv_fs_write(uv_default_loop(), req, m_file, &buf, 1, 0, FileLog::onWrite);
}

50
src/log/FileLog.h Normal file
View File

@@ -0,0 +1,50 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 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 __FILELOG_H__
#define __FILELOG_H__
#include <uv.h>
#include "interfaces/ILogBackend.h"
class FileLog : public ILogBackend
{
public:
FileLog(const char *fileName);
void message(int level, const char* fmt, va_list args) override;
void text(const char* fmt, va_list args) override;
private:
static void onWrite(uv_fs_t *req);
void write(char *data, size_t size);
int m_file;
};
#endif /* __FILELOG_H__ */

79
src/log/Log.cpp Normal file
View File

@@ -0,0 +1,79 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 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 <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef WIN32
# include <winsock2.h>
# include <malloc.h>
# include "3rdparty/winansi.h"
#endif
#include "interfaces/ILogBackend.h"
#include "log/Log.h"
Log *Log::m_self = nullptr;
void Log::message(Log::Level level, const char* fmt, ...)
{
va_list args;
va_list copy;
va_start(args, fmt);
for (ILogBackend *backend : m_backends) {
va_copy(copy, args);
backend->message(level, fmt, copy);
va_end(copy);
}
}
void Log::text(const char* fmt, ...)
{
va_list args;
va_list copy;
va_start(args, fmt);
for (ILogBackend *backend : m_backends) {
va_copy(copy, args);
backend->text(fmt, copy);
va_end(copy);
}
va_end(args);
}
Log::~Log()
{
for (auto backend : m_backends) {
delete backend;
}
}

View File

@@ -21,14 +21,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __CONSOLE_H__ #ifndef __LOG_H__
#define __CONSOLE_H__ #define __LOG_H__
#include <uv.h> #include <uv.h>
#include <vector>
class Console class ILogBackend;
class Log
{ {
public: public:
enum Level { enum Level {
@@ -50,34 +54,35 @@ public:
constexpr static const char* kCL_GRAY = "\x1B[90m"; constexpr static const char* kCL_GRAY = "\x1B[90m";
# endif # endif
static inline Console* i() { return m_self; } static inline Log* i() { return m_self; }
static void init(); static inline void add(ILogBackend *backend) { i()->m_backends.push_back(backend); }
static inline void init() { if (!m_self) { m_self = new Log();} }
void message(Level level, const char* fmt, ...); void message(Level level, const char* fmt, ...);
void text(const char* fmt, ...); void text(const char* fmt, ...);
private: private:
Console(); inline Log() {}
~Log();
static Console *m_self; static Log *m_self;
bool m_colors; std::vector<ILogBackend*> m_backends;
uv_mutex_t m_mutex;
}; };
#define LOG_ERR(x, ...) Console::i()->message(Console::ERR, x, ##__VA_ARGS__) #define LOG_ERR(x, ...) Log::i()->message(Log::ERR, x, ##__VA_ARGS__)
#define LOG_WARN(x, ...) Console::i()->message(Console::WARNING, x, ##__VA_ARGS__) #define LOG_WARN(x, ...) Log::i()->message(Log::WARNING, x, ##__VA_ARGS__)
#define LOG_NOTICE(x, ...) Console::i()->message(Console::NOTICE, x, ##__VA_ARGS__) #define LOG_NOTICE(x, ...) Log::i()->message(Log::NOTICE, x, ##__VA_ARGS__)
#define LOG_INFO(x, ...) Console::i()->message(Console::INFO, x, ##__VA_ARGS__) #define LOG_INFO(x, ...) Log::i()->message(Log::INFO, x, ##__VA_ARGS__)
#ifdef APP_DEBUG #ifdef APP_DEBUG
# define LOG_DEBUG(x, ...) Console::i()->message(Console::DEBUG, x, ##__VA_ARGS__) # define LOG_DEBUG(x, ...) Log::i()->message(Log::DEBUG, x, ##__VA_ARGS__)
# define LOG_DEBUG_ERR(x, ...) Console::i()->message(Console::ERR, x, ##__VA_ARGS__) # define LOG_DEBUG_ERR(x, ...) Log::i()->message(Log::ERR, x, ##__VA_ARGS__)
# define LOG_DEBUG_WARN(x, ...) Console::i()->message(Console::WARNING, x, ##__VA_ARGS__) # define LOG_DEBUG_WARN(x, ...) Log::i()->message(Log::WARNING, x, ##__VA_ARGS__)
#else #else
# define LOG_DEBUG(x, ...) # define LOG_DEBUG(x, ...)
# define LOG_DEBUG_ERR(x, ...) # define LOG_DEBUG_ERR(x, ...)
# define LOG_DEBUG_WARN(x, ...) # define LOG_DEBUG_WARN(x, ...)
#endif #endif
#endif /* __CONSOLE_H__ */ #endif /* __LOG_H__ */

47
src/log/SysLog.cpp Normal file
View File

@@ -0,0 +1,47 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 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 <syslog.h>
#include "log/SysLog.h"
#include "version.h"
SysLog::SysLog()
{
openlog(APP_ID, LOG_PID, LOG_USER);
}
void SysLog::message(int level, const char *fmt, va_list args)
{
vsyslog(level, fmt, args);
}
void SysLog::text(const char *fmt, va_list args)
{
message(LOG_INFO, fmt, args);
}

40
src/log/SysLog.h Normal file
View File

@@ -0,0 +1,40 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 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 __SYSLOG_H__
#define __SYSLOG_H__
#include "interfaces/ILogBackend.h"
class SysLog : public ILogBackend
{
public:
SysLog();
void message(int level, const char *fmt, va_list args) override;
void text(const char *fmt, va_list args) override;
};
#endif /* __SYSLOG_BACKEND_H__ */

View File

@@ -22,10 +22,11 @@
*/ */
#include <iterator>
#include <utility> #include <utility>
#include "Console.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/JobResult.h"
@@ -37,9 +38,9 @@
#endif #endif
Client::Client(int id, IClientListener *listener) : Client::Client(int id, const char *agent, IClientListener *listener) :
m_keepAlive(false), m_quiet(false),
m_host(nullptr), m_agent(agent),
m_listener(listener), m_listener(listener),
m_id(id), m_id(id),
m_retryPause(5000), m_retryPause(5000),
@@ -47,16 +48,17 @@ Client::Client(int id, IClientListener *listener) :
m_sequence(1), m_sequence(1),
m_recvBufPos(0), m_recvBufPos(0),
m_state(UnconnectedState), m_state(UnconnectedState),
m_port(0),
m_stream(nullptr), m_stream(nullptr),
m_socket(nullptr) m_socket(nullptr)
{ {
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;
@@ -72,13 +74,12 @@ Client::~Client()
{ {
free(m_recvBuf.base); free(m_recvBuf.base);
free(m_socket); free(m_socket);
free(m_host);
} }
void Client::connect() void Client::connect()
{ {
resolve(m_host); resolve(m_url.host());
} }
@@ -90,30 +91,19 @@ void Client::connect()
void Client::connect(const Url *url) void Client::connect(const Url *url)
{ {
setUrl(url); setUrl(url);
resolve(m_host); resolve(m_url.host());
} }
void Client::disconnect() void Client::disconnect()
{ {
uv_timer_stop(&m_retriesTimer);
m_failures = -1; m_failures = -1;
close(); close();
} }
void Client::login(const char *user, const char *pass, const char *agent)
{
m_sequence = 1;
const size_t size = 96 + strlen(user) + strlen(pass) + strlen(agent);
char *req = static_cast<char*>(malloc(size));
snprintf(req, size, "{\"id\":%llu,\"jsonrpc\":\"2.0\",\"method\":\"login\",\"params\":{\"login\":\"%s\",\"pass\":\"%s\",\"agent\":\"%s\"}}\n", m_sequence, user, pass, agent);
send(req);
}
/** /**
* @brief Send raw data to server. * @brief Send raw data to server.
* *
@@ -121,9 +111,9 @@ void Client::login(const char *user, const char *pass, const char *agent)
*/ */
void Client::send(char *data) void Client::send(char *data)
{ {
LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_host, m_port, strlen(data), data); LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), strlen(data), data);
if (state() != ConnectedState) { if (state() != ConnectedState) {
LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_host, m_port, m_state); LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state);
return; return;
} }
@@ -148,9 +138,7 @@ void Client::setUrl(const Url *url)
return; return;
} }
free(m_host); m_url = url;
m_host = strdup(url->host());
m_port = url->port();
} }
@@ -169,6 +157,7 @@ void Client::submit(const JobResult &result)
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\":%llu,\"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);
send(req); send(req);
} }
@@ -180,7 +169,7 @@ bool Client::parseJob(const json_t *params, int *code)
return false; return false;
} }
Job job; Job job(m_id, m_url.isNicehash());
if (!job.setId(json_string_value(json_object_get(params, "job_id")))) { if (!job.setId(json_string_value(json_object_get(params, "job_id")))) {
*code = 3; *code = 3;
return false; return false;
@@ -196,10 +185,9 @@ bool Client::parseJob(const json_t *params, int *code)
return false; return false;
} }
job.setPoolId(m_id);
m_job = std::move(job); m_job = std::move(job);
LOG_DEBUG("[%s:%u] job: \"%s\", diff: %lld", m_host, m_port, job.id(), job.diff()); LOG_DEBUG("[%s:%u] job: \"%s\", diff: %lld", m_url.host(), m_url.port(), job.id(), job.diff());
return true; return true;
} }
@@ -225,9 +213,15 @@ int Client::resolve(const char *host)
m_recvBufPos = 0; m_recvBufPos = 0;
if (m_failures == -1) {
m_failures = 0;
}
const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host, NULL, &m_hints); const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host, NULL, &m_hints);
if (r) { if (r) {
LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host, m_port, uv_strerror(r)); if (!m_quiet) {
LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host, m_url.port(), uv_strerror(r));
}
return 1; return 1;
} }
@@ -250,7 +244,7 @@ void Client::connect(struct sockaddr *addr)
{ {
setState(ConnectingState); setState(ConnectingState);
reinterpret_cast<struct sockaddr_in*>(addr)->sin_port = htons(m_port); reinterpret_cast<struct sockaddr_in*>(addr)->sin_port = htons(m_url.port());
free(m_socket); free(m_socket);
uv_connect_t *req = (uv_connect_t*) malloc(sizeof(uv_connect_t)); uv_connect_t *req = (uv_connect_t*) malloc(sizeof(uv_connect_t));
@@ -261,25 +255,43 @@ void Client::connect(struct sockaddr *addr)
uv_tcp_init(uv_default_loop(), m_socket); uv_tcp_init(uv_default_loop(), m_socket);
uv_tcp_nodelay(m_socket, 1); uv_tcp_nodelay(m_socket, 1);
# ifndef WIN32
uv_tcp_keepalive(m_socket, 1, 60); uv_tcp_keepalive(m_socket, 1, 60);
# endif
uv_tcp_connect(req, m_socket, (const sockaddr*) addr, Client::onConnect); uv_tcp_connect(req, m_socket, (const sockaddr*) addr, Client::onConnect);
} }
void Client::login()
{
m_sequence = 1;
m_results.clear();
const size_t size = 96 + strlen(m_url.user()) + strlen(m_url.password()) + strlen(m_agent);
char *req = static_cast<char*>(malloc(size));
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);
send(req);
}
void Client::parse(char *line, size_t len) void Client::parse(char *line, size_t len)
{ {
startTimeout(); startTimeout();
line[len - 1] = '\0'; line[len - 1] = '\0';
LOG_DEBUG("[%s:%u] received (%d bytes): \"%s\"", m_host, m_port, len, line); LOG_DEBUG("[%s:%u] received (%d bytes): \"%s\"", m_url.host(), m_url.port(), len, line);
json_error_t err; json_error_t err;
json_t *val = json_loads(line, 0, &err); json_t *val = json_loads(line, 0, &err);
if (!val) { if (!val) {
LOG_ERR("[%s:%u] JSON decode failed: \"%s\"", m_host, m_port, err.text); if (!m_quiet) {
LOG_ERR("[%s:%u] JSON decode failed: \"%s\"", m_url.host(), m_url.port(), err.text);
}
return; return;
} }
@@ -298,7 +310,9 @@ void Client::parse(char *line, size_t len)
void Client::parseNotification(const char *method, const json_t *params, const json_t *error) void Client::parseNotification(const char *method, const json_t *params, const json_t *error)
{ {
if (json_is_object(error)) { if (json_is_object(error)) {
LOG_ERR("[%s:%u] error: \"%s\", code: %lld", m_host, m_port, json_string_value(json_object_get(error, "message")), json_integer_value(json_object_get(error, "code"))); 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")));
}
return; return;
} }
@@ -315,7 +329,7 @@ void Client::parseNotification(const char *method, const json_t *params, const j
return; return;
} }
LOG_WARN("[%s:%u] unsupported method: \"%s\"", m_host, m_port, method); LOG_WARN("[%s:%u] unsupported method: \"%s\"", m_url.host(), m_url.port(), method);
} }
@@ -323,7 +337,15 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
{ {
if (json_is_object(error)) { if (json_is_object(error)) {
const char *message = json_string_value(json_object_get(error, "message")); const char *message = json_string_value(json_object_get(error, "message"));
LOG_ERR("[%s:%u] error: \"%s\", code: %lld", m_host, m_port, message, json_integer_value(json_object_get(error, "code")));
auto it = m_results.find(id);
if (it != m_results.end()) {
m_listener->onResultAccepted(this, it->second.diff, it->second.elapsed(), message);
m_results.erase(it);
}
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")));
}
if (id == 1 || (message && strncasecmp(message, "Unauthenticated", 15) == 0)) { if (id == 1 || (message && strncasecmp(message, "Unauthenticated", 15) == 0)) {
close(); close();
@@ -339,7 +361,10 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
if (id == 1) { if (id == 1) {
int code = -1; int code = -1;
if (!parseLogin(result, &code)) { if (!parseLogin(result, &code)) {
LOG_ERR("[%s:%u] login error code: %d", m_host, m_port, code); if (!m_quiet) {
LOG_ERR("[%s:%u] login error code: %d", m_url.host(), m_url.port(), code);
}
return close(); return close();
} }
@@ -348,6 +373,12 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
m_listener->onJobReceived(this, m_job); m_listener->onJobReceived(this, m_job);
return; return;
} }
auto it = m_results.find(id);
if (it != m_results.end()) {
m_listener->onResultAccepted(this, it->second.diff, it->second.elapsed(), nullptr);
m_results.erase(it);
}
} }
@@ -362,8 +393,10 @@ void Client::ping()
void Client::reconnect() void Client::reconnect()
{ {
setState(ConnectingState);
uv_timer_stop(&m_responseTimer); uv_timer_stop(&m_responseTimer);
if (m_keepAlive) { if (m_url.isKeepAlive()) {
uv_timer_stop(&m_keepAliveTimer); uv_timer_stop(&m_keepAliveTimer);
} }
@@ -380,7 +413,7 @@ void Client::reconnect()
void Client::setState(SocketState state) void Client::setState(SocketState state)
{ {
LOG_DEBUG("[%s:%u] state: %d", m_host, m_port, state); LOG_DEBUG("[%s:%u] state: %d", m_url.host(), m_url.port(), state);
if (m_state == state) { if (m_state == state) {
return; return;
@@ -393,7 +426,7 @@ void Client::setState(SocketState state)
void Client::startTimeout() void Client::startTimeout()
{ {
uv_timer_stop(&m_responseTimer); uv_timer_stop(&m_responseTimer);
if (!m_keepAlive) { if (!m_url.isKeepAlive()) {
return; return;
} }
@@ -428,7 +461,10 @@ void Client::onConnect(uv_connect_t *req, int status)
{ {
auto client = getClient(req->data); auto client = getClient(req->data);
if (status < 0) { if (status < 0) {
LOG_ERR("[%s:%u] connect error: \"%s\"", client->m_host, client->m_port, uv_strerror(status)); if (!client->m_quiet) {
LOG_ERR("[%s:%u] connect error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status));
}
free(req); free(req);
client->close(); client->close();
return; return;
@@ -441,7 +477,7 @@ void Client::onConnect(uv_connect_t *req, int status)
uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead); uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead);
free(req); free(req);
client->m_listener->onLoginCredentialsRequired(client); client->login();
} }
@@ -449,8 +485,8 @@ void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
{ {
auto client = getClient(stream->data); auto client = getClient(stream->data);
if (nread < 0) { if (nread < 0) {
if (nread != UV_EOF) { if (nread != UV_EOF && !client->m_quiet) {
LOG_ERR("[%s:%u] read error: \"%s\"", client->m_host, client->m_port, uv_strerror(nread)); LOG_ERR("[%s:%u] read error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(nread));
} }
return client->close();; return client->close();;
@@ -489,10 +525,12 @@ void Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res)
{ {
auto client = getClient(req->data); auto client = getClient(req->data);
if (status < 0) { if (status < 0) {
LOG_ERR("[%s:%u] DNS error: \"%s\"", client->m_host, client->m_port, uv_strerror(status)); LOG_ERR("[%s:%u] DNS error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status));
return client->reconnect();; return client->reconnect();;
} }
uv_ip4_name(reinterpret_cast<sockaddr_in*>(res->ai_addr), client->m_ip, 16);
client->connect(res->ai_addr); client->connect(res->ai_addr);
uv_freeaddrinfo(res); uv_freeaddrinfo(res);
} }

View File

@@ -26,15 +26,17 @@
#include <jansson.h> #include <jansson.h>
#include <map>
#include <uv.h> #include <uv.h>
#include "net/Job.h" #include "net/Job.h"
#include "net/SubmitResult.h"
#include "net/Url.h"
class IClientListener; class IClientListener;
class JobResult; class JobResult;
class Url;
class Client class Client
@@ -48,27 +50,27 @@ public:
ClosingState ClosingState
}; };
constexpr static int kResponseTimeout = 15 * 1000; constexpr static int kResponseTimeout = 20 * 1000;
constexpr static int kKeepAliveTimeout = 60 * 1000; constexpr static int kKeepAliveTimeout = 60 * 1000;
Client(int id, IClientListener *listener); Client(int id, const char *agent, IClientListener *listener);
~Client(); ~Client();
void connect(); void connect();
void connect(const Url *url); void connect(const Url *url);
void disconnect(); void disconnect();
void login(const char *user, const char *pass, const char *agent);
void send(char *data); void send(char *data);
void setUrl(const Url *url); void setUrl(const Url *url);
void submit(const JobResult &result); 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_host; } inline const char *host() const { return m_url.host(); }
inline const char *ip() const { return m_ip; }
inline const Job &job() const { return m_job; } inline const Job &job() const { return m_job; }
inline int id() const { return m_id; } inline int id() const { return m_id; }
inline SocketState state() const { return m_state; } inline SocketState state() const { return m_state; }
inline uint16_t port() const { return m_port; } inline uint16_t port() const { return m_url.port(); }
inline void setKeepAlive(bool keepAlive) { m_keepAlive = keepAlive; } inline void setQuiet(bool quiet) { m_quiet = quiet; }
inline void setRetryPause(int ms) { m_retryPause = ms; } inline void setRetryPause(int ms) { m_retryPause = ms; }
private: private:
@@ -79,6 +81,7 @@ private:
int resolve(const char *host); int resolve(const char *host);
void close(); void close();
void connect(struct sockaddr *addr); void connect(struct sockaddr *addr);
void login();
void parse(char *line, size_t len); void parse(char *line, size_t len);
void parseNotification(const char *method, const json_t *params, const json_t *error); void parseNotification(const char *method, const json_t *params, const json_t *error);
void parseResponse(int64_t id, const json_t *result, const json_t *error); void parseResponse(int64_t id, const json_t *result, const json_t *error);
@@ -95,9 +98,10 @@ private:
static Client *getClient(void *data); static Client *getClient(void *data);
bool m_keepAlive; bool m_quiet;
char *m_host; char m_ip[17];
char m_rpcId[64]; char m_rpcId[64];
const char *m_agent;
IClientListener *m_listener; IClientListener *m_listener;
int m_id; int m_id;
int m_retryPause; int m_retryPause;
@@ -106,8 +110,9 @@ private:
Job m_job; Job m_job;
size_t m_recvBufPos; size_t m_recvBufPos;
SocketState m_state; SocketState m_state;
std::map<int64_t, SubmitResult> m_results;
struct addrinfo m_hints; struct addrinfo m_hints;
uint16_t m_port; Url m_url;
uv_buf_t m_recvBuf; uv_buf_t m_recvBuf;
uv_getaddrinfo_t m_resolver; uv_getaddrinfo_t m_resolver;
uv_stream_t *m_stream; uv_stream_t *m_stream;

View File

@@ -23,11 +23,10 @@
#include <string.h> #include <string.h>
//#include <stdlib.h>
#include "log/Log.h"
#include "net/Job.h" #include "net/Job.h"
#include "Console.h"
static inline unsigned char hf_hex2bin(char c, bool &err) static inline unsigned char hf_hex2bin(char c, bool &err)
@@ -57,7 +56,8 @@ static inline char hf_bin2hex(unsigned char c)
} }
Job::Job(int poolId) : Job::Job(int poolId, bool nicehash) :
m_nicehash(nicehash),
m_poolId(poolId), m_poolId(poolId),
m_size(0), m_size(0),
m_diff(0), m_diff(0),
@@ -82,7 +82,15 @@ 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;
}
return true;
} }

View File

@@ -34,20 +34,21 @@
class Job class Job
{ {
public: public:
Job(int poolId = -2); Job(int poolId = -2, bool nicehash = false);
bool setBlob(const char *blob); bool setBlob(const char *blob);
bool setId(const char *id); bool setId(const char *id);
bool setTarget(const char *target); bool setTarget(const char *target);
inline bool isValid() const { return m_size > 0 && m_diff > 0; } inline bool isNicehash() const { return m_nicehash; }
inline const char *id() const { return m_id; } inline bool isValid() const { return m_size > 0 && m_diff > 0; }
inline const uint8_t *blob() const { return m_blob; } inline const char *id() const { return m_id; }
inline int poolId() const { return m_poolId; } inline const uint8_t *blob() const { return m_blob; }
inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); } inline int poolId() const { return m_poolId; }
inline uint32_t diff() const { return m_diff; } inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); }
inline uint32_t size() const { return m_size; } inline uint32_t diff() const { return m_diff; }
inline uint64_t target() const { return m_target; } inline uint32_t size() const { return m_size; }
inline void setPoolId(int poolId) { m_poolId = poolId; } inline uint64_t target() const { return m_target; }
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
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); }
@@ -55,6 +56,7 @@ public:
static void toHex(const unsigned char* in, unsigned int len, char* out); static void toHex(const unsigned char* in, unsigned int len, char* out);
private: private:
bool m_nicehash;
int m_poolId; int m_poolId;
VAR_ALIGN(16, char m_id[64]); VAR_ALIGN(16, char m_id[64]);
VAR_ALIGN(16, uint8_t m_blob[84]); // Max blob size is 84 (75 fixed + 9 variable), aligned to 96. https://github.com/xmrig/xmrig/issues/1 Thanks fireice-uk. VAR_ALIGN(16, uint8_t m_blob[84]); // Max blob size is 84 (75 fixed + 9 variable), aligned to 96. https://github.com/xmrig/xmrig/issues/1 Thanks fireice-uk.

View File

@@ -29,18 +29,32 @@
#include <stdint.h> #include <stdint.h>
#include "Job.h"
class JobResult class JobResult
{ {
public: public:
inline JobResult() : poolId(0), nonce(0) {} inline JobResult() : poolId(0), diff(0), nonce(0) {}
inline JobResult(int poolId, const char *jobId, uint32_t nonce, const uint8_t *result) : poolId(poolId), nonce(nonce) inline JobResult(int poolId, const char *jobId, uint32_t nonce, const uint8_t *result, uint32_t diff) : poolId(poolId), diff(diff), nonce(nonce)
{ {
memcpy(this->jobId, jobId, sizeof(this->jobId)); memcpy(this->jobId, jobId, sizeof(this->jobId));
memcpy(this->result, result, sizeof(this->result)); memcpy(this->result, result, sizeof(this->result));
} }
inline JobResult &operator=(const Job &job) {
memcpy(jobId, job.id(), sizeof(jobId));
poolId = job.poolId();
diff = job.diff();
return *this;
}
char jobId[64]; char jobId[64];
int poolId; int poolId;
uint32_t diff;
uint32_t nonce; uint32_t nonce;
uint8_t result[32]; uint8_t result[32];
}; };

View File

@@ -25,79 +25,68 @@
#include <memory> #include <memory>
#include "Console.h" #include "log/Log.h"
#include "net/Client.h" #include "net/Client.h"
#include "net/Network.h" #include "net/Network.h"
#include "net/strategies/DonateStrategy.h"
#include "net/strategies/FailoverStrategy.h"
#include "net/strategies/SinglePoolStrategy.h"
#include "net/Url.h" #include "net/Url.h"
#include "Options.h" #include "Options.h"
#include "workers/Workers.h" #include "workers/Workers.h"
Network::Network(const Options *options) : Network::Network(const Options *options) :
m_donate(false), m_donateActive(false),
m_options(options), m_options(options),
m_pool(0), m_donate(nullptr),
m_diff(0) m_accepted(0),
m_rejected(0)
{ {
Workers::setListener(this); Workers::setListener(this);
m_pools.reserve(2);
m_agent = userAgent(); m_agent = userAgent();
addPool(std::make_unique<Url>().get()); const std::vector<Url*> &pools = options->pools();
addPool(m_options->url());
addPool(m_options->backupUrl());
m_timer.data = this; if (pools.size() > 1) {
uv_timer_init(uv_default_loop(), &m_timer); m_strategy = new FailoverStrategy(pools, m_agent, this);
}
else {
m_strategy = new SinglePoolStrategy(pools.front(), m_agent, this);
}
if (m_options->donateLevel() > 0) {
m_donate = new DonateStrategy(m_agent, this);
}
} }
Network::~Network() Network::~Network()
{ {
for (auto client : m_pools) {
delete client;
}
free(m_agent); free(m_agent);
} }
void Network::connect() void Network::connect()
{ {
m_pools[1]->connect(); m_strategy->connect();
if (m_options->donateLevel()) {
uv_timer_start(&m_timer, Network::onTimer, (100 - m_options->donateLevel()) * 60 * 1000, 0);
}
} }
void Network::onClose(Client *client, int failures) void Network::onActive(Client *client)
{ {
const int id = client->id(); if (client->id() == -1) {
if (id == 0) { LOG_NOTICE("dev donate started");
if (failures == -1) {
stopDonate();
}
return; return;
} }
if (m_pool == id) { LOG_INFO(m_options->colors() ? "\x1B[01;37muse pool \x1B[01;36m%s:%d \x1B[01;30m%s" : "use pool %s:%d %s", client->host(), client->port(), client->ip());
m_pool = 0;
Workers::pause();
}
if (id == 1 && m_pools.size() > 2 && failures == m_options->retries()) {
m_pools[2]->connect();
}
} }
void Network::onJobReceived(Client *client, const Job &job) void Network::onJob(Client *client, const Job &job)
{ {
if (m_donate && client->id() != 0) { if (m_donate && m_donate->isActive() && client->id() != -1) {
return; return;
} }
@@ -107,117 +96,52 @@ void Network::onJobReceived(Client *client, const Job &job)
void Network::onJobResult(const JobResult &result) void Network::onJobResult(const JobResult &result)
{ {
if (m_options->colors()) { if (result.poolId == -1 && m_donate) {
LOG_NOTICE("\x1B[01;32mSHARE FOUND"); return m_donate->submit(result);
}
m_strategy->submit(result);
}
void Network::onPause(IStrategy *strategy)
{
if (m_donate && m_donate == strategy) {
LOG_NOTICE("dev donate finished");
m_strategy->resume();
}
if (!m_strategy->isActive()) {
LOG_ERR("no active pools, pause mining");
return Workers::pause();
}
}
void Network::onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error)
{
if (error) {
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);
} }
else { else {
LOG_NOTICE("SHARE FOUND"); 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);
} }
m_pools[result.poolId]->submit(result);
}
void Network::onLoginCredentialsRequired(Client *client)
{
client->login(m_options->user(), m_options->pass(), m_agent);
}
void Network::onLoginSuccess(Client *client)
{
const int id = client->id();
if (id == 0) {
return startDonate();
}
if (id == 2 && m_pool) { // primary pool is already active
m_pools[2]->disconnect();
return;
}
LOG_NOTICE("use pool: \"%s:%d\"", client->host(), client->port());
m_pool = id;
if (m_pool == 1 && m_pools.size() > 2) { // try disconnect from backup pool
m_pools[2]->disconnect();
}
}
void Network::addPool(const Url *url)
{
if (!url) {
return;
}
Client *client = new Client(m_pools.size(), this);
client->setUrl(url);
client->setRetryPause(m_options->retryPause() * 1000);
client->setKeepAlive(m_options->keepAlive());
m_pools.push_back(client);
} }
void Network::setJob(Client *client, const Job &job) void Network::setJob(Client *client, const Job &job)
{ {
if (m_options->colors()) { if (m_options->colors()) {
LOG_INFO("\x1B[01;35mnew job\x1B[0m from \"%s:%d\", diff: %d", client->host(), client->port(), job.diff()); LOG_INFO("\x1B[01;35mnew job\x1B[0m from \x1B[01;37m%s:%d\x1B[0m diff \x1B[01;37m%d", client->host(), client->port(), job.diff());
} }
else { else {
LOG_INFO("new job from \"%s:%d\", diff: %d", client->host(), client->port(), job.diff()); LOG_INFO("new job from %s:%d diff %d", client->host(), client->port(), job.diff());
} }
Workers::setJob(job); Workers::setJob(job);
} }
void Network::startDonate()
{
if (m_donate) {
return;
}
LOG_NOTICE("dev donate started");
m_donate = true;
}
void Network::stopDonate()
{
if (!m_donate) {
return;
}
LOG_NOTICE("dev donate finished");
m_donate = false;
if (!m_pool) {
return;
}
Client *client = m_pools[m_pool];
if (client->isReady()) {
setJob(client, client->job());
}
}
void Network::onTimer(uv_timer_t *handle)
{
auto net = static_cast<Network*>(handle->data);
if (!net->m_donate) {
auto url = std::make_unique<Url>("donate.xmrig.com", net->m_options->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443);
net->m_pools[0]->connect(url.get());
uv_timer_start(&net->m_timer, Network::onTimer, net->m_options->donateLevel() * 60 * 1000, 0);
return;
}
net->m_pools[0]->disconnect();
uv_timer_start(&net->m_timer, Network::onTimer, (100 - net->m_options->donateLevel()) * 60 * 1000, 0);
}

View File

@@ -31,13 +31,15 @@
#include "interfaces/IClientListener.h" #include "interfaces/IClientListener.h"
#include "interfaces/IJobResultListener.h" #include "interfaces/IJobResultListener.h"
#include "interfaces/IStrategyListener.h"
class IStrategy;
class Options; class Options;
class Url; class Url;
class Network : public IClientListener, public IJobResultListener class Network : public IJobResultListener, public IStrategyListener
{ {
public: public:
Network(const Options *options); Network(const Options *options);
@@ -48,11 +50,11 @@ public:
static char *userAgent(); static char *userAgent();
protected: protected:
void onClose(Client *client, int failures) override; void onActive(Client *client) override;
void onJobReceived(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 onLoginCredentialsRequired(Client *client) override; void onPause(IStrategy *strategy) override;
void onLoginSuccess(Client *client) override; void onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) override;
private: private:
void addPool(const Url *url); void addPool(const Url *url);
@@ -60,15 +62,13 @@ private:
void startDonate(); void startDonate();
void stopDonate(); void stopDonate();
static void onTimer(uv_timer_t *handle); bool m_donateActive;
bool m_donate;
char *m_agent; char *m_agent;
const Options *m_options; const Options *m_options;
int m_pool; IStrategy *m_donate;
std::vector<Client*> m_pools; IStrategy *m_strategy;
uint64_t m_diff; uint64_t m_accepted;
uv_timer_t m_timer; uint64_t m_rejected;
}; };

47
src/net/SubmitResult.h Normal file
View File

@@ -0,0 +1,47 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 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 __SUBMITRESULT_H__
#define __SUBMITRESULT_H__
#include <uv.h>
class SubmitResult
{
public:
inline SubmitResult() : diff(0), start(0) {}
inline SubmitResult(uint32_t diff) :
diff(diff)
{
start = uv_hrtime();
}
inline uint64_t elapsed() const { return (uv_hrtime() - start) / 1000000; }
uint32_t diff;
uint64_t start;
};
#endif /* __SUBMITRESULT_H__ */

View File

@@ -35,8 +35,12 @@
Url::Url() : Url::Url() :
m_keepAlive(false),
m_nicehash(false),
m_host(nullptr), m_host(nullptr),
m_port(3333) m_password(nullptr),
m_user(nullptr),
m_port(kDefaultPort)
{ {
} }
@@ -53,40 +57,22 @@ Url::Url() :
* @param url * @param url
*/ */
Url::Url(const char *url) : Url::Url(const char *url) :
m_keepAlive(false),
m_nicehash(false),
m_host(nullptr), m_host(nullptr),
m_port(3333) m_password(nullptr),
m_user(nullptr),
m_port(kDefaultPort)
{ {
const char *p = strstr(url, "://"); parse(url);
const char *base = url;
if (p) {
if (strncasecmp(url, "stratum+tcp://", 14)) {
return;
}
base = url + 14;
}
if (!strlen(base) || *base == '/') {
return;
}
const char *port = strchr(base, ':');
if (!port) {
m_host = strdup(base);
return;
}
const size_t size = port++ - base + 1;
m_host = static_cast<char*>(malloc(size));
memcpy(m_host, base, size - 1);
m_host[size - 1] = '\0';
m_port = strtol(port, nullptr, 10);
} }
Url::Url(const char *host, uint16_t port) : Url::Url(const char *host, uint16_t port, const char *user, const char *password, bool keepAlive, bool nicehash) :
m_keepAlive(keepAlive),
m_nicehash(nicehash),
m_password(password ? strdup(password) : nullptr),
m_user(user ? strdup(user) : nullptr),
m_port(port) m_port(port)
{ {
m_host = strdup(host); m_host = strdup(host);
@@ -96,10 +82,101 @@ Url::Url(const char *host, uint16_t port) :
Url::~Url() Url::~Url()
{ {
free(m_host); free(m_host);
free(m_password);
free(m_user);
} }
bool Url::isNicehash() const bool Url::isNicehash() const
{ {
return isValid() && strstr(m_host, ".nicehash.com"); return isValid() && (m_nicehash || strstr(m_host, ".nicehash.com"));
}
bool Url::parse(const char *url)
{
const char *p = strstr(url, "://");
const char *base = url;
if (p) {
if (strncasecmp(url, "stratum+tcp://", 14)) {
return false;
}
base = url + 14;
}
if (!strlen(base) || *base == '/') {
return false;
}
const char *port = strchr(base, ':');
if (!port) {
m_host = strdup(base);
return false;
}
const size_t size = port++ - base + 1;
m_host = static_cast<char*>(malloc(size));
memcpy(m_host, base, size - 1);
m_host[size - 1] = '\0';
m_port = strtol(port, nullptr, 10);
return true;
}
bool Url::setUserpass(const char *userpass)
{
const char *p = strchr(userpass, ':');
if (!p) {
return false;
}
free(m_user);
free(m_password);
m_user = static_cast<char*>(calloc(p - userpass + 1, 1));
strncpy(m_user, userpass, p - userpass);
m_password = strdup(p + 1);
return true;
}
void Url::setPassword(const char *password)
{
if (!password) {
return;
}
free(m_password);
m_password = strdup(password);
}
void Url::setUser(const char *user)
{
if (!user) {
return;
}
free(m_user);
m_user = strdup(user);
}
Url &Url::operator=(const Url *other)
{
m_keepAlive = other->m_keepAlive;
m_nicehash = other->m_nicehash;
m_port = other->m_port;
free(m_host);
m_host = strdup(other->m_host);
setPassword(other->m_password);
setUser(other->m_user);
return *this;
} }

View File

@@ -31,19 +31,38 @@
class Url class Url
{ {
public: public:
constexpr static const char *kDefaultPassword = "x";
constexpr static const char *kDefaultUser = "x";
constexpr static uint16_t kDefaultPort = 3333;
Url(); Url();
Url(const char *url); Url(const char *url);
Url(const char *host, uint16_t port); Url(const char *host, uint16_t port, const char *user = nullptr, const char *password = nullptr, bool keepAlive = false, bool nicehash = false );
~Url(); ~Url();
bool isNicehash() const; inline bool isKeepAlive() const { return m_keepAlive; }
inline bool isValid() const { return m_host && m_port > 0; }
inline const char *host() const { return m_host; }
inline const char *password() const { return m_password ? m_password : kDefaultPassword; }
inline const char *user() const { return m_user ? m_user : kDefaultUser; }
inline uint16_t port() const { return m_port; }
inline void setKeepAlive(bool keepAlive) { m_keepAlive = keepAlive; }
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
inline bool isValid() const { return m_host && m_port > 0; } bool isNicehash() const;
inline const char *host() const { return m_host; } bool parse(const char *url);
inline uint16_t port() const { return m_port; } bool setUserpass(const char *userpass);
void setPassword(const char *password);
void setUser(const char *user);
Url &operator=(const Url *other);
private: private:
bool m_keepAlive;
bool m_nicehash;
char *m_host; char *m_host;
char *m_password;
char *m_user;
uint16_t m_port; uint16_t m_port;
}; };

View File

@@ -0,0 +1,119 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 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 "interfaces/IStrategyListener.h"
#include "net/Client.h"
#include "net/strategies/DonateStrategy.h"
#include "Options.h"
DonateStrategy::DonateStrategy(const char *agent, IStrategyListener *listener) :
m_active(false),
m_donateTime(Options::i()->donateLevel() * 60 * 1000),
m_idleTime((100 - Options::i()->donateLevel()) * 60 * 1000),
m_listener(listener)
{
Url *url = new Url("donate2.xmrig.com", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443, Options::i()->pools().front()->user());
m_client = new Client(-1, agent, this);
m_client->setUrl(url);
m_client->setRetryPause(Options::i()->retryPause() * 1000);
m_client->setQuiet(true);
delete url;
m_timer.data = this;
uv_timer_init(uv_default_loop(), &m_timer);
idle();
}
void DonateStrategy::connect()
{
m_client->connect();
}
void DonateStrategy::submit(const JobResult &result)
{
m_client->submit(result);
}
void DonateStrategy::onClose(Client *client, int failures)
{
}
void DonateStrategy::onJobReceived(Client *client, const Job &job)
{
m_listener->onJob(client, job);
}
void DonateStrategy::onLoginSuccess(Client *client)
{
if (!isActive()) {
uv_timer_start(&m_timer, DonateStrategy::onTimer, m_donateTime, 0);
}
m_active = true;
m_listener->onActive(client);
}
void DonateStrategy::onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error)
{
m_listener->onResultAccepted(client, diff, ms, error);
}
void DonateStrategy::idle()
{
uv_timer_start(&m_timer, DonateStrategy::onTimer, m_idleTime, 0);
}
void DonateStrategy::stop()
{
m_client->disconnect();
m_active = false;
m_listener->onPause(this);
idle();
}
void DonateStrategy::onTimer(uv_timer_t *handle)
{
auto strategy = static_cast<DonateStrategy*>(handle->data);
if (!strategy->isActive()) {
return strategy->connect();
}
strategy->stop();
}

View File

@@ -0,0 +1,72 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 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 __DONATESTRATEGY_H__
#define __DONATESTRATEGY_H__
#include <uv.h>
#include "interfaces/IClientListener.h"
#include "interfaces/IStrategy.h"
class Client;
class IStrategyListener;
class Url;
class DonateStrategy : public IStrategy, public IClientListener
{
public:
DonateStrategy(const char *agent, IStrategyListener *listener);
public:
inline bool isActive() const override { return m_active; }
inline void resume() override {}
void connect() override;
void submit(const JobResult &result) override;
protected:
void onClose(Client *client, int failures) override;
void onJobReceived(Client *client, const Job &job) override;
void onLoginSuccess(Client *client) override;
void onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) override;
private:
void idle();
void stop();
static void onTimer(uv_timer_t *handle);
bool m_active;
Client *m_client;
const int m_donateTime;
const int m_idleTime;
IStrategyListener *m_listener;
uv_timer_t m_timer;
};
#endif /* __DONATESTRATEGY_H__ */

View File

@@ -0,0 +1,127 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 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 "interfaces/IStrategyListener.h"
#include "net/Client.h"
#include "net/strategies/FailoverStrategy.h"
#include "Options.h"
FailoverStrategy::FailoverStrategy(const std::vector<Url*> &urls, const char *agent, IStrategyListener *listener) :
m_active(-1),
m_index(0),
m_listener(listener)
{
for (const Url *url : urls) {
add(url, agent);
}
}
void FailoverStrategy::connect()
{
m_pools[m_index]->connect();
}
void FailoverStrategy::resume()
{
if (!isActive()) {
return;
}
m_listener->onJob( m_pools[m_active], m_pools[m_active]->job());
}
void FailoverStrategy::submit(const JobResult &result)
{
m_pools[m_active]->submit(result);
}
void FailoverStrategy::onClose(Client *client, int failures)
{
if (failures == -1) {
return;
}
if (m_active == client->id()) {
m_active = -1;
m_listener->onPause(this);
}
if (m_index == 0 && failures < Options::i()->retries()) {
return;
}
if (m_index == client->id() && (m_pools.size() - m_index) > 1) {
m_pools[++m_index]->connect();
}
}
void FailoverStrategy::onJobReceived(Client *client, const Job &job)
{
if (m_active == client->id()) {
m_listener->onJob(client, job);
}
}
void FailoverStrategy::onLoginSuccess(Client *client)
{
int active = m_active;
if (client->id() == 0 || !isActive()) {
active = client->id();
}
for (size_t i = 1; i < m_pools.size(); ++i) {
if (active != static_cast<int>(i)) {
m_pools[i]->disconnect();
}
}
if (active >= 0 && active != m_active) {
m_index = m_active = active;
m_listener->onActive(client);
}
}
void FailoverStrategy::onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error)
{
m_listener->onResultAccepted(client, diff, ms, error);
}
void FailoverStrategy::add(const Url *url, const char *agent)
{
Client *client = new Client(m_pools.size(), agent, this);
client->setUrl(url);
client->setRetryPause(Options::i()->retryPause() * 1000);
m_pools.push_back(client);
}

View File

@@ -0,0 +1,67 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 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 __FAILOVERSTRATEGY_H__
#define __FAILOVERSTRATEGY_H__
#include <vector>
#include "interfaces/IClientListener.h"
#include "interfaces/IStrategy.h"
class Client;
class IStrategyListener;
class Url;
class FailoverStrategy : public IStrategy, public IClientListener
{
public:
FailoverStrategy(const std::vector<Url*> &urls, const char *agent, IStrategyListener *listener);
public:
inline bool isActive() const override { return m_active >= 0; }
void connect() override;
void resume() override;
void submit(const JobResult &result) override;
protected:
void onClose(Client *client, int failures) override;
void onJobReceived(Client *client, const Job &job) override;
void onLoginSuccess(Client *client) override;
void onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) override;
private:
void add(const Url *url, const char *agent);
int m_active;
int m_index;
IStrategyListener *m_listener;
std::vector<Client*> m_pools;
};
#endif /* __FAILOVERSTRATEGY_H__ */

View File

@@ -0,0 +1,90 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 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 "interfaces/IStrategyListener.h"
#include "net/Client.h"
#include "net/strategies/SinglePoolStrategy.h"
#include "Options.h"
SinglePoolStrategy::SinglePoolStrategy(const Url *url, const char *agent, IStrategyListener *listener) :
m_active(false),
m_listener(listener)
{
m_client = new Client(0, agent, this);
m_client->setUrl(url);
m_client->setRetryPause(Options::i()->retryPause() * 1000);
}
void SinglePoolStrategy::connect()
{
m_client->connect();
}
void SinglePoolStrategy::resume()
{
if (!isActive()) {
return;
}
m_listener->onJob(m_client, m_client->job());
}
void SinglePoolStrategy::submit(const JobResult &result)
{
m_client->submit(result);
}
void SinglePoolStrategy::onClose(Client *client, int failures)
{
if (!isActive()) {
return;
}
m_active = false;
m_listener->onPause(this);
}
void SinglePoolStrategy::onJobReceived(Client *client, const Job &job)
{
m_listener->onJob(client, job);
}
void SinglePoolStrategy::onLoginSuccess(Client *client)
{
m_active = true;
m_listener->onActive(client);
}
void SinglePoolStrategy::onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error)
{
m_listener->onResultAccepted(client, diff, ms, error);
}

View File

@@ -0,0 +1,61 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 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 __SINGLEPOOLSTRATEGY_H__
#define __SINGLEPOOLSTRATEGY_H__
#include "interfaces/IClientListener.h"
#include "interfaces/IStrategy.h"
class Client;
class IStrategyListener;
class Url;
class SinglePoolStrategy : public IStrategy, public IClientListener
{
public:
SinglePoolStrategy(const Url *url, const char *agent, IStrategyListener *listener);
public:
inline bool isActive() const override { return m_active; }
void connect() override;
void resume() override;
void submit(const JobResult &result) override;
protected:
void onClose(Client *client, int failures) override;
void onJobReceived(Client *client, const Job &job) override;
void onLoginSuccess(Client *client) override;
void onResultAccepted(Client *client, uint32_t diff, uint64_t ms, const char *error) override;
private:
bool m_active;
Client *m_client;
IStrategyListener *m_listener;
};
#endif /* __SINGLEPOOLSTRATEGY_H__ */

View File

@@ -27,14 +27,14 @@
#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 "1.0.0" #define APP_VERSION "2.0.1"
#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 1 #define APP_VER_MAJOR 2
#define APP_VER_MINOR 0 #define APP_VER_MINOR 0
#define APP_VER_BUILD 0 #define APP_VER_BUILD 1
#define APP_VER_REV 0 #define APP_VER_REV 0
#ifdef _MSC_VER #ifdef _MSC_VER

View File

@@ -30,11 +30,33 @@
#include "workers/Workers.h" #include "workers/Workers.h"
DoubleWorker::DoubleWorker(Handle *handle) class DoubleWorker::State
: Worker(handle),
m_nonce1(0),
m_nonce2(0)
{ {
public:
inline State() :
nonce1(0),
nonce2(0)
{}
Job job;
uint32_t nonce1;
uint32_t nonce2;
uint8_t blob[84 * 2];
};
DoubleWorker::DoubleWorker(Handle *handle)
: Worker(handle)
{
m_state = new State();
m_pausedState = new State();
}
DoubleWorker::~DoubleWorker()
{
delete m_state;
delete m_pausedState;
} }
@@ -56,17 +78,17 @@ void DoubleWorker::start()
} }
m_count += 2; m_count += 2;
*Job::nonce(m_blob) = ++m_nonce1; *Job::nonce(m_state->blob) = ++m_state->nonce1;
*Job::nonce(m_blob + m_job.size()) = ++m_nonce2; *Job::nonce(m_state->blob + m_state->job.size()) = ++m_state->nonce2;
CryptoNight::hash(m_blob, m_job.size(), m_hash, m_ctx); CryptoNight::hash(m_state->blob, m_state->job.size(), m_hash, m_ctx);
if (*reinterpret_cast<uint64_t*>(m_hash + 24) < m_job.target()) { if (*reinterpret_cast<uint64_t*>(m_hash + 24) < m_state->job.target()) {
Workers::submit(JobResult(m_job.poolId(), m_job.id(), m_nonce1, m_hash)); Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce1, m_hash, m_state->job.diff()));
} }
if (*reinterpret_cast<uint64_t*>(m_hash + 32 + 24) < m_job.target()) { if (*reinterpret_cast<uint64_t*>(m_hash + 32 + 24) < m_state->job.target()) {
Workers::submit(JobResult(m_job.poolId(), m_job.id(), m_nonce2, m_hash + 32)); Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce2, m_hash + 32, m_state->job.diff()));
} }
std::this_thread::yield(); std::this_thread::yield();
@@ -77,20 +99,46 @@ void DoubleWorker::start()
} }
bool DoubleWorker::resume(const Job &job)
{
if (m_state->job.poolId() == -1 && job.poolId() >= 0 && memcmp(job.id(), m_pausedState->job.id(), 64) == 0) {
*m_state = *m_pausedState;
return true;
}
return false;
}
void DoubleWorker::consumeJob() void DoubleWorker::consumeJob()
{ {
m_job = Workers::job(); Job job = Workers::job();
m_sequence = Workers::sequence(); m_sequence = Workers::sequence();
memcpy(m_blob, m_job.blob(), m_job.size()); save(job);
memcpy(m_blob + m_job.size(), m_job.blob(), m_job.size());
if (m_nicehash) { if (resume(job)) {
m_nonce1 = (*Job::nonce(m_blob) & 0xff000000U) + (0xffffffU / (m_threads * 2) * m_id); return;
m_nonce2 = (*Job::nonce(m_blob + m_job.size()) & 0xff000000U) + (0xffffffU / (m_threads * 2) * (m_id + m_threads)); }
m_state->job = std::move(job);
memcpy(m_state->blob, m_state->job.blob(), m_state->job.size());
memcpy(m_state->blob + m_state->job.size(), m_state->job.blob(), m_state->job.size());
if (m_state->job.isNicehash()) {
m_state->nonce1 = (*Job::nonce(m_state->blob) & 0xff000000U) + (0xffffffU / (m_threads * 2) * m_id);
m_state->nonce2 = (*Job::nonce(m_state->blob + m_state->job.size()) & 0xff000000U) + (0xffffffU / (m_threads * 2) * (m_id + m_threads));
} }
else { else {
m_nonce1 = 0xffffffffU / (m_threads * 2) * m_id; m_state->nonce1 = 0xffffffffU / (m_threads * 2) * m_id;
m_nonce2 = 0xffffffffU / (m_threads * 2) * (m_id + m_threads); m_state->nonce2 = 0xffffffffU / (m_threads * 2) * (m_id + m_threads);
}
}
void DoubleWorker::save(const Job &job)
{
if (job.poolId() == -1 && m_state->job.poolId() >= 0) {
*m_pausedState = *m_state;
} }
} }

View File

@@ -38,17 +38,20 @@ class DoubleWorker : public Worker
{ {
public: public:
DoubleWorker(Handle *handle); DoubleWorker(Handle *handle);
~DoubleWorker();
void start() override; void start() override;
private: private:
bool resume(const Job &job);
void consumeJob(); void consumeJob();
void save(const Job &job);
class State;
Job m_job;
uint32_t m_nonce1;
uint32_t m_nonce2;
uint8_t m_hash[64]; uint8_t m_hash[64];
uint8_t m_blob[84 * 2]; State *m_state;
State *m_pausedState;
}; };

View File

@@ -25,8 +25,7 @@
#include "workers/Handle.h" #include "workers/Handle.h"
Handle::Handle(int threadId, int threads, int64_t affinity, bool nicehash) : Handle::Handle(int threadId, int threads, int64_t affinity) :
m_nicehash(nicehash),
m_threadId(threadId), m_threadId(threadId),
m_threads(threads), m_threads(threads),
m_affinity(affinity), m_affinity(affinity),

View File

@@ -35,10 +35,9 @@ class IWorker;
class Handle class Handle
{ {
public: public:
Handle(int threadId, int threads, int64_t affinity, bool nicehash); Handle(int threadId, int threads, int64_t affinity);
void start(void (*callback) (void *)); void start(void (*callback) (void *));
inline bool nicehash() const { return m_nicehash; }
inline int threadId() const { return m_threadId; } inline int threadId() const { return m_threadId; }
inline int threads() const { return m_threads; } inline int threads() const { return m_threads; }
inline int64_t affinity() const { return m_affinity; } inline int64_t affinity() const { return m_affinity; }
@@ -46,7 +45,6 @@ public:
inline void setWorker(IWorker *worker) { m_worker = worker; } inline void setWorker(IWorker *worker) { m_worker = worker; }
private: private:
bool m_nicehash;
int m_threadId; int m_threadId;
int m_threads; int m_threads;
int64_t m_affinity; int64_t m_affinity;

View File

@@ -26,7 +26,7 @@
#include <cmath> #include <cmath>
#include <memory.h> #include <memory.h>
#include "Console.h" #include "log/Log.h"
#include "Options.h" #include "Options.h"
#include "workers/Hashrate.h" #include "workers/Hashrate.h"
@@ -152,7 +152,7 @@ void Hashrate::print()
char num3[8]; char num3[8];
char num4[8]; char num4[8];
LOG_INFO(Options::i()->colors() ? "\x1B[01;37mspeed\x1B[0m 2.5s/60s/15m \x1B[01;36m%s \x1B[22;36m%s %s \x1B[01;36mH/s\x1B[0m highest: \x1B[01;36m%s H/s" : "speed 2.5s/60s/15m %s %s %s H/s highest: %s H/s", LOG_INFO(Options::i()->colors() ? "\x1B[01;37mspeed\x1B[0m 2.5s/60s/15m \x1B[01;36m%s \x1B[22;36m%s %s \x1B[01;36mH/s\x1B[0m max: \x1B[01;36m%s H/s" : "speed 2.5s/60s/15m %s %s %s H/s max: %s H/s",
format(calc(2500), num1, sizeof(num1)), format(calc(2500), num1, sizeof(num1)),
format(calc(60000), num2, sizeof(num2)), format(calc(60000), num2, sizeof(num2)),
format(calc(900000), num3, sizeof(num3)), format(calc(900000), num3, sizeof(num3)),

View File

@@ -68,19 +68,45 @@ void SingleWorker::start()
} }
bool SingleWorker::resume(const Job &job)
{
if (m_job.poolId() == -1 && job.poolId() >= 0 && memcmp(job.id(), m_paused.id(), 64) == 0) {
m_job = m_paused;
m_result = m_job;
m_result.nonce = *m_job.nonce();
return true;
}
return false;
}
void SingleWorker::consumeJob() void SingleWorker::consumeJob()
{ {
m_job = Workers::job(); Job job = Workers::job();
m_sequence = Workers::sequence(); m_sequence = Workers::sequence();
memcpy(m_result.jobId, m_job.id(), sizeof(m_result.jobId)); save(job);
m_result.poolId = m_job.poolId();
if (m_nicehash) { if (resume(job)) {
return;
}
m_job = std::move(job);
m_result = m_job;
if (m_job.isNicehash()) {
m_result.nonce = (*m_job.nonce() & 0xff000000U) + (0xffffffU / m_threads * m_id); m_result.nonce = (*m_job.nonce() & 0xff000000U) + (0xffffffU / m_threads * m_id);
} }
else { else {
m_result.nonce = 0xffffffffU / m_threads * m_id; m_result.nonce = 0xffffffffU / m_threads * m_id;
} }
} }
void SingleWorker::save(const Job &job)
{
if (job.poolId() == -1 && m_job.poolId() >= 0) {
m_paused = m_job;
}
}

View File

@@ -41,9 +41,12 @@ public:
void start() override; void start() override;
private: private:
bool resume(const Job &job);
void consumeJob(); void consumeJob();
void save(const Job &job);
Job m_job; Job m_job;
Job m_paused;
JobResult m_result; JobResult m_result;
}; };

View File

@@ -23,7 +23,6 @@
#include <chrono> #include <chrono>
#include "Console.h"
#include "Cpu.h" #include "Cpu.h"
#include "Mem.h" #include "Mem.h"
@@ -32,7 +31,6 @@
Worker::Worker(Handle *handle) : Worker::Worker(Handle *handle) :
m_nicehash(handle->nicehash()),
m_id(handle->threadId()), m_id(handle->threadId()),
m_threads(handle->threads()), m_threads(handle->threads()),
m_hashCount(0), m_hashCount(0),

View File

@@ -48,7 +48,6 @@ public:
protected: protected:
void storeStats(); void storeStats();
bool m_nicehash;
cryptonight_ctx *m_ctx; cryptonight_ctx *m_ctx;
int m_id; int m_id;
int m_threads; int m_threads;

View File

@@ -24,7 +24,6 @@
#include <cmath> #include <cmath>
#include "Console.h"
#include "interfaces/IJobResultListener.h" #include "interfaces/IJobResultListener.h"
#include "Mem.h" #include "Mem.h"
#include "Options.h" #include "Options.h"
@@ -70,7 +69,7 @@ void Workers::setJob(const Job &job)
} }
void Workers::start(int64_t affinity, bool nicehash) void Workers::start(int64_t affinity)
{ {
const int threads = Mem::threads(); const int threads = Mem::threads();
m_hashrate = new Hashrate(threads); m_hashrate = new Hashrate(threads);
@@ -86,7 +85,7 @@ void Workers::start(int64_t affinity, bool nicehash)
uv_timer_start(&m_timer, Workers::onTick, 500, 500); uv_timer_start(&m_timer, Workers::onTick, 500, 500);
for (int i = 0; i < threads; ++i) { for (int i = 0; i < threads; ++i) {
Handle *handle = new Handle(i, threads, affinity, nicehash); Handle *handle = new Handle(i, threads, affinity);
m_workers.push_back(handle); m_workers.push_back(handle);
handle->start(Workers::onReady); handle->start(Workers::onReady);
} }

View File

@@ -44,13 +44,13 @@ class Workers
public: public:
static Job job(); static Job job();
static void setJob(const Job &job); static void setJob(const Job &job);
static void start(int64_t affinity, bool nicehash); static void start(int64_t affinity);
static void submit(const JobResult &result); static void submit(const JobResult &result);
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; } static inline void pause() { 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: