Merge branch 'dev'

bug-68
XMRig 2017-08-20 10:24:49 +03:00
commit f041571674
49 changed files with 747 additions and 168 deletions

View File

@ -1,3 +1,13 @@
# v2.3.0
- Added `--cpu-priority` option (0 idle, 2 normal to 5 highest).
- Added `--user-agent` option, to set custom user-agent string for pool. For example `cpuminer-multi/0.1`.
- Added `--no-huge-pages` option, to disable huge pages support.
- [#62](https://github.com/xmrig/xmrig/issues/62) Don't send the login to the dev pool.
- Force reconnect if pool block miner IP address. helps switch to backup pool.
- Fixed: failed open default config file if path contains non English characters.
- Fixed: error occurred if try use unavailable stdin or stdout, regression since version 2.2.0.
- Fixed: message about huge pages support successfully enabled on Windows was not shown in release builds.
# v2.2.1
- Fixed [terminal issues](https://github.com/xmrig/xmrig-proxy/issues/2#issuecomment-319914085) after exit on Linux and OS X.

View File

@ -28,12 +28,13 @@ set(HEADERS
src/net/Job.h
src/net/JobResult.h
src/net/Network.h
src/net/SubmitResult.h
src/net/Url.h
src/net/strategies/DonateStrategy.h
src/net/strategies/FailoverStrategy.h
src/net/strategies/SinglePoolStrategy.h
src/net/SubmitResult.h
src/net/Url.h
src/Options.h
src/Platform.h
src/Summary.h
src/version.h
src/workers/DoubleWorker.h
@ -73,6 +74,7 @@ set(SOURCES
src/net/strategies/SinglePoolStrategy.cpp
src/net/Url.cpp
src/Options.cpp
src/Platform.cpp
src/Summary.cpp
src/workers/DoubleWorker.cpp
src/workers/Handle.cpp
@ -100,7 +102,7 @@ if (WIN32)
src/App_win.cpp
src/Cpu_win.cpp
src/Mem_win.cpp
src/net/Network_win.cpp
src/Platform_win.cpp
)
add_definitions(/DWIN32)
@ -110,14 +112,14 @@ elseif (APPLE)
src/App_unix.cpp
src/Cpu_mac.cpp
src/Mem_unix.cpp
src/net/Network_mac.cpp
src/Platform_mac.cpp
)
else()
set(SOURCES_OS
src/App_unix.cpp
src/Cpu_unix.cpp
src/Mem_unix.cpp
src/net/Network_unix.cpp
src/Platform_unix.cpp
)
set(EXTRA_LIBS pthread)
@ -159,6 +161,8 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Ox /Ot /Oi /MT /GL")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ox /Ot /Oi /MT /GL")
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
add_definitions(/D_CRT_NONSTDC_NO_WARNINGS)
elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)

View File

@ -2,7 +2,9 @@
XMRig is high performance Monero (XMR) CPU miner, with the official full Windows support.
Originally based on cpuminer-multi with heavy optimizations/rewrites and removing a lot of legacy code, since version 1.0.0 complete rewritten from scratch on C++.
<img src="https://i.imgur.com/OXoB10D.png" width="628" >
* This is the CPU-mining version, there is also a [NVIDIA GPU version](https://github.com/xmrig/xmrig-nvidia).
<img src="http://i.imgur.com/OKZRVDh.png" width="619" >
#### Table of contents
* [Features](#features)
@ -30,17 +32,17 @@ Originally based on cpuminer-multi with heavy optimizations/rewrites and removin
## Download
* Binary releases: https://github.com/xmrig/xmrig/releases
* Git tree: https://github.com/xmrig/xmrig.git
* Clone with `git clone https://github.com/xmrig/xmrig.git`
* Clone with `git clone https://github.com/xmrig/xmrig.git` :hammer: [Build instructions](https://github.com/xmrig/xmrig/wiki/Build).
## Usage
### Basic example
```
xmrig.exe -o xmr-eu.dwarfpool.com:8005 -u YOUR_WALLET -p x -k
xmrig.exe -o pool.minemonero.pro:5555 -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
xmrig.exe -o pool.minemonero.pro:5555 -u YOUR_WALLET1 -p x -k -o pool.supportxmr.com:5555 -u YOUR_WALLET2 -p x -k
```
For failover you can add multiple pools, maximum count not limited.
@ -56,19 +58,25 @@ For failover you can add multiple pools, maximum count not limited.
-k, --keepalive send keepalived for prevent timeout (need pool support)
-r, --retries=N number of times to retry before switch to backup server (default: 5)
-R, --retry-pause=N time to pause between retries (default: 5)
--cpu-affinity set process affinity to cpu core(s), mask 0x3 for cores 0 and 1
--cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1
--cpu-priority set process priority (0 idle, 2 normal to 5 highest)
--no-huge-pages disable huge pages support
--no-color disable colored output
--donate-level=N donate level, default 5% (5 minutes in 100 minutes)
--user-agent set custom user-agent string for pool
-B, --background run the miner in the background
-c, --config=FILE load a JSON-format configuration file
--max-cpu-usage=N maximum cpu usage for automatic threads mode (default 75)
--safe safe adjust threads and av settings for current cpu
-l, --log-file=FILE log all output to a file
--max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)
--safe safe adjust threads and av settings for current CPU
--nicehash enable nicehash support
--print-time=N print hashrate report every N seconds
-h, --help display this help and exit
-V, --version output version information and exit
```
Also you can use configuration via config file, default **config.json**. You can load multiple config files and combine it with command line options.
## Algorithm variations
Since version 0.8.0.
* `--av=1` For CPUs with hardware AES.
@ -88,8 +96,8 @@ Since version 0.8.0.
### CPU mining performance
* **i7-6700** - 290+ H/s (4 threads, cpu affinity 0xAA)
* **Dual E5620** - 377 H/s (12 threads, cpu affinity 0xEEEE)
* **Intel i7-7700** - 307 H/s (4 threads)
* **AMD Ryzen 7 1700X** - 560 H/s (8 threads)
Please note performance is highly dependent on system load. The numbers above are obtained on an idle system. Tasks heavily using a processor cache, such as video playback, can greatly degrade hashrate. Optimal number of threads depends on the size of the L3 cache of a processor, 1 thread requires 2 MB of cache.

View File

@ -56,7 +56,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#pragma warning(disable:4996);
#pragma warning(disable:4996)
#define __GETOPT_H__

View File

@ -5,6 +5,10 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifdef _MSC_VER
#pragma warning(disable:4090)
#endif
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
@ -15,8 +19,11 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#if defined(HAVE_UNISTD_H)
# include <unistd.h>
#elif defined(_MSC_VER)
# include <io.h>
#endif
#include "jansson.h"
@ -62,10 +69,13 @@ static int dump_to_file(const char *buffer, size_t size, void *data)
static int dump_to_fd(const char *buffer, size_t size, void *data)
{
int *dest = (int *)data;
#ifdef HAVE_UNISTD_H
# if defined(HAVE_UNISTD_H)
if(write(*dest, buffer, size) == (ssize_t)size)
return 0;
#endif
# elif (defined(_MSC_VER))
if (write(*dest, buffer, (unsigned int) size) == (int) size)
return 0;
# endif
return -1;
}

View File

@ -5,6 +5,10 @@
* it under the terms of the MIT license. See LICENSE for details.
*/
#ifdef _MSC_VER
#pragma warning(disable:4334)
#endif
#if HAVE_CONFIG_H
#include <jansson_private_config.h>
#endif

View File

@ -17,8 +17,13 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#if defined(HAVE_UNISTD_H)
# include <unistd.h>
#elif defined(_MSC_VER)
# include <io.h>
# define HAVE_UNISTD_H
# define STDIN_FILENO 0
#endif
#include "jansson.h"
@ -1034,8 +1039,8 @@ json_t *json_loadf(FILE *input, size_t flags, json_error_t *error)
static int fd_get_func(int *fd)
{
uint8_t c;
#ifdef HAVE_UNISTD_H
uint8_t c;
if (read(*fd, &c, 1) == 1)
return c;
#endif

View File

@ -36,6 +36,7 @@
#include "Mem.h"
#include "net/Network.h"
#include "Options.h"
#include "Platform.h"
#include "Summary.h"
#include "version.h"
#include "workers/Workers.h"
@ -80,6 +81,9 @@ App::App(int argc, char **argv) :
}
# endif
Platform::init(m_options->userAgent());
Platform::setProcessPriority(m_options->priority());
m_network = new Network(m_options);
uv_signal_init(uv_default_loop(), &m_signal);
@ -109,10 +113,10 @@ int App::exec()
return 1;
}
Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash());
Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash(), m_options->hugePages());
Summary::print();
Workers::start(m_options->affinity());
Workers::start(m_options->affinity(), m_options->priority());
m_network->connect();
@ -120,10 +124,11 @@ int App::exec()
uv_loop_close(uv_default_loop());
uv_tty_reset_mode();
free(m_network);
free(m_options);
delete m_network;
Options::release();
Mem::release();
Platform::release();
return r;
}

View File

@ -68,7 +68,7 @@ int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage)
}
if (((float) count / m_totalThreads * 100) > maxCpuUsage) {
count = ceil((float) m_totalThreads * (maxCpuUsage / 100.0));
count = (int) ceil((float) m_totalThreads * (maxCpuUsage / 100.0));
}
return count < 1 ? 1 : count;

View File

@ -41,8 +41,8 @@ public:
static void init();
static void setAffinity(int id, uint64_t mask);
static inline bool hasAES() { return m_flags & AES; }
static inline bool isX64() { return m_flags & X86_64; }
static inline bool hasAES() { return (m_flags & AES) != 0; }
static inline bool isX64() { return (m_flags & X86_64) != 0; }
static inline const char *brand() { return m_brand; }
static inline int cores() { return m_totalCores; }
static inline int l2() { return m_l2_cache; }

View File

@ -44,14 +44,14 @@ public:
Lock = 4
};
static bool allocate(int algo, int threads, bool doubleHash);
static bool allocate(int algo, int threads, bool doubleHash, bool enabled);
static cryptonight_ctx *create(int threadId);
static void *calloc(size_t num, size_t size);
static void release();
static inline bool isDoubleHash() { return m_doubleHash; }
static inline bool isHugepagesAvailable() { return m_flags & HugepagesAvailable; }
static inline bool isHugepagesEnabled() { return m_flags & HugepagesEnabled; }
static inline bool isHugepagesAvailable() { return (m_flags & HugepagesAvailable) != 0; }
static inline bool isHugepagesEnabled() { return (m_flags & HugepagesEnabled) != 0; }
static inline int flags() { return m_flags; }
static inline int threads() { return m_threads; }

View File

@ -33,7 +33,7 @@
#include "Options.h"
bool Mem::allocate(int algo, int threads, bool doubleHash)
bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled)
{
m_algo = algo;
m_threads = threads;
@ -42,6 +42,11 @@ bool Mem::allocate(int algo, int threads, bool doubleHash)
const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
const size_t size = MEMORY * (threads * ratio + 1);
if (!enabled) {
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
return true;
}
m_flags |= HugepagesAvailable;
# if defined(__APPLE__)

View File

@ -85,9 +85,8 @@ static BOOL SetLockPagesPrivilege() {
static LSA_UNICODE_STRING StringToLsaUnicodeString(LPCTSTR string) {
LSA_UNICODE_STRING lsaString;
DWORD dwLen = 0;
dwLen = wcslen(string);
DWORD dwLen = (DWORD) wcslen(string);
lsaString.Buffer = (LPWSTR) string;
lsaString.Length = (USHORT)((dwLen) * sizeof(WCHAR));
lsaString.MaximumLength = (USHORT)((dwLen + 1) * sizeof(WCHAR));
@ -124,7 +123,7 @@ static BOOL ObtainLockPagesPrivilege() {
LSA_UNICODE_STRING str = StringToLsaUnicodeString(_T(SE_LOCK_MEMORY_NAME));
if (LsaAddAccountRights(handle, user->User.Sid, &str, 1) == 0) {
LOG_DEBUG("Huge pages support was successfully enabled, but reboot required to use it");
LOG_NOTICE("Huge pages support was successfully enabled, but reboot required to use it");
result = TRUE;
}
@ -145,7 +144,7 @@ static BOOL TrySetLockPagesPrivilege() {
}
bool Mem::allocate(int algo, int threads, bool doubleHash)
bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled)
{
m_algo = algo;
m_threads = threads;
@ -154,6 +153,11 @@ bool Mem::allocate(int algo, int threads, bool doubleHash)
const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
const size_t size = MEMORY * (threads * ratio + 1);
if (!enabled) {
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
return true;
}
if (TrySetLockPagesPrivilege()) {
m_flags |= HugepagesAvailable;
}

View File

@ -38,6 +38,7 @@
#include "donate.h"
#include "net/Url.h"
#include "Options.h"
#include "Platform.h"
#include "version.h"
@ -63,8 +64,11 @@ Options:\n\
-r, --retries=N number of times to retry before switch to backup server (default: 5)\n\
-R, --retry-pause=N time to pause between retries (default: 5)\n\
--cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1\n\
--cpu-priority set process priority (0 idle, 2 normal to 5 highest)\n\
--no-huge-pages disable huge pages support\n\
--no-color disable colored output\n\
--donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\
--user-agent set custom user-agent string for pool\n\
-B, --background run the miner in the background\n\
-c, --config=FILE load a JSON-format configuration file\n\
-l, --log-file=FILE log all output to a file\n"
@ -91,6 +95,7 @@ static struct option const options[] = {
{ "background", 0, nullptr, 'B' },
{ "config", 1, nullptr, 'c' },
{ "cpu-affinity", 1, nullptr, 1020 },
{ "cpu-priority", 1, nullptr, 1021 },
{ "donate-level", 1, nullptr, 1003 },
{ "help", 0, nullptr, 'h' },
{ "keepalive", 0, nullptr ,'k' },
@ -98,6 +103,7 @@ static struct option const options[] = {
{ "max-cpu-usage", 1, nullptr, 1004 },
{ "nicehash", 0, nullptr, 1006 },
{ "no-color", 0, nullptr, 1002 },
{ "no-huge-pages", 0, nullptr, 1009 },
{ "pass", 1, nullptr, 'p' },
{ "print-time", 1, nullptr, 1007 },
{ "retries", 1, nullptr, 'r' },
@ -107,6 +113,7 @@ static struct option const options[] = {
{ "threads", 1, nullptr, 't' },
{ "url", 1, nullptr, 'o' },
{ "user", 1, nullptr, 'u' },
{ "user-agent", 1, nullptr, 1008 },
{ "userpass", 1, nullptr, 'O' },
{ "version", 0, nullptr, 'V' },
{ 0, 0, 0, 0 }
@ -117,8 +124,11 @@ static struct option const config_options[] = {
{ "algo", 1, nullptr, 'a' },
{ "av", 1, nullptr, 'v' },
{ "background", 0, nullptr, 'B' },
{ "colors", 0, nullptr, 2000 },
{ "cpu-affinity", 1, nullptr, 1020 },
{ "cpu-priority", 1, nullptr, 1021 },
{ "donate-level", 1, nullptr, 1003 },
{ "huge-pages", 0, nullptr, 1009 },
{ "log-file", 1, nullptr, 'l' },
{ "max-cpu-usage", 1, nullptr, 1004 },
{ "print-time", 1, nullptr, 1007 },
@ -127,7 +137,7 @@ static struct option const config_options[] = {
{ "safe", 0, nullptr, 1005 },
{ "syslog", 0, nullptr, 'S' },
{ "threads", 1, nullptr, 't' },
{ "colors", 0, nullptr, 2000 },
{ "user-agent", 1, nullptr, 1008 },
{ 0, 0, 0, 0 }
};
@ -151,34 +161,6 @@ static const char *algo_names[] = {
};
static char *defaultConfigName()
{
size_t size = 512;
char *buf = new char[size];
if (uv_exepath(buf, &size) < 0) {
delete [] buf;
return nullptr;
}
if (size < 500) {
# ifdef WIN32
char *p = strrchr(buf, '\\');
# else
char *p = strrchr(buf, '/');
# endif
if (p) {
strcpy(p + 1, "config.json");
return buf;
}
}
delete [] buf;
return nullptr;
}
Options *Options::parse(int argc, char **argv)
{
Options *options = new Options(argc, argv);
@ -202,15 +184,18 @@ Options::Options(int argc, char **argv) :
m_background(false),
m_colors(true),
m_doubleHash(false),
m_hugePages(true),
m_ready(false),
m_safe(false),
m_syslog(false),
m_logFile(nullptr),
m_userAgent(nullptr),
m_algo(0),
m_algoVariant(0),
m_donateLevel(kDonateLevel),
m_maxCpuUsage(75),
m_printTime(60),
m_priority(-1),
m_retries(5),
m_retryPause(5),
m_threads(0),
@ -237,9 +222,7 @@ Options::Options(int argc, char **argv) :
}
if (!m_pools[0]->isValid()) {
char *fileName = defaultConfigName();
parseConfig(fileName);
delete [] fileName;
parseConfig(Platform::defaultConfigName());
}
if (!m_pools[0]->isValid()) {
@ -326,16 +309,20 @@ bool Options::parseArg(int key, const char *arg)
case 1003: /* --donate-level */
case 1004: /* --max-cpu-usage */
case 1007: /* --print-time */
case 1021: /* --cpu-priority */
return parseArg(key, strtol(arg, nullptr, 10));
case 'B': /* --background */
case 'k': /* --keepalive */
case 'S': /* --syslog */
case 1002: /* --no-color */
case 1005: /* --safe */
case 1006: /* --nicehash */
return parseBoolean(key, true);
case 1002: /* --no-color */
case 1009: /* --no-huge-pages */
return parseBoolean(key, false);
case 'V': /* --version */
showVersion();
return false;
@ -353,6 +340,11 @@ bool Options::parseArg(int key, const char *arg)
return parseArg(key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10));
}
case 1008: /* --user-agent */
free(m_userAgent);
m_userAgent = strdup(arg);
break;
default:
showUsage(1);
return false;
@ -371,7 +363,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false;
}
m_retries = arg;
m_retries = (int) arg;
break;
case 'R': /* --retry-pause */
@ -380,7 +372,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false;
}
m_retryPause = arg;
m_retryPause = (int) arg;
break;
case 't': /* --threads */
@ -389,7 +381,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false;
}
m_threads = arg;
m_threads = (int) arg;
break;
case 'v': /* --av */
@ -398,7 +390,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false;
}
m_algoVariant = arg;
m_algoVariant = (int) arg;
break;
case 1003: /* --donate-level */
@ -407,7 +399,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false;
}
m_donateLevel = arg;
m_donateLevel = (int) arg;
break;
case 1004: /* --max-cpu-usage */
@ -416,7 +408,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false;
}
m_maxCpuUsage = arg;
m_maxCpuUsage = (int) arg;
break;
case 1007: /* --print-time */
@ -425,7 +417,7 @@ bool Options::parseArg(int key, uint64_t arg)
return false;
}
m_printTime = arg;
m_printTime = (int) arg;
break;
case 1020: /* --cpu-affinity */
@ -434,6 +426,12 @@ bool Options::parseArg(int key, uint64_t arg)
}
break;
case 1021: /* --cpu-priority */
if (arg <= 5) {
m_priority = (int) arg;
}
break;
default:
break;
}
@ -471,6 +469,10 @@ bool Options::parseBoolean(int key, bool enable)
m_pools.back()->setNicehash(enable);
break;
case 1009: /* --no-huge-pages */
m_hugePages = enable;
break;
case 2000: /* colors */
m_colors = enable;
break;
@ -497,8 +499,20 @@ Url *Options::parseUrl(const char *arg) const
void Options::parseConfig(const char *fileName)
{
uv_fs_t req;
const int fd = uv_fs_open(uv_default_loop(), &req, fileName, O_RDONLY, 0644, nullptr);
if (fd < 0) {
fprintf(stderr, "unable to open %s: %s\n", fileName, uv_strerror(fd));
return;
}
uv_fs_req_cleanup(&req);
json_error_t err;
json_t *config = json_load_file(fileName, 0, &err);
json_t *config = json_loadfd(fd, 0, &err);
uv_fs_close(uv_default_loop(), &req, fd, nullptr);
uv_fs_req_cleanup(&req);
if (!json_is_object(config)) {
if (config) {
@ -609,7 +623,7 @@ bool Options::setAlgo(const char *algo)
{
for (size_t i = 0; i < ARRAY_SIZE(algo_names); i++) {
if (algo_names[i] && !strcmp(algo, algo_names[i])) {
m_algo = i;
m_algo = (int) i;
break;
}

View File

@ -57,18 +57,23 @@ public:
inline bool background() const { return m_background; }
inline bool colors() const { return m_colors; }
inline bool doubleHash() const { return m_doubleHash; }
inline bool hugePages() const { return m_hugePages; }
inline bool syslog() const { return m_syslog; }
inline const char *logFile() const { return m_logFile; }
inline const char *userAgent() const { return m_userAgent; }
inline const std::vector<Url*> &pools() const { return m_pools; }
inline int algo() const { return m_algo; }
inline int algoVariant() const { return m_algoVariant; }
inline int donateLevel() const { return m_donateLevel; }
inline int printTime() const { return m_printTime; }
inline int priority() const { return m_priority; }
inline int retries() const { return m_retries; }
inline int retryPause() const { return m_retryPause; }
inline int threads() const { return m_threads; }
inline int64_t affinity() const { return m_affinity; }
inline static void release() { delete m_self; }
const char *algoName() const;
private:
@ -98,15 +103,18 @@ private:
bool m_background;
bool m_colors;
bool m_doubleHash;
bool m_hugePages;
bool m_ready;
bool m_safe;
bool m_syslog;
char *m_logFile;
char *m_userAgent;
int m_algo;
int m_algoVariant;
int m_donateLevel;
int m_maxCpuUsage;
int m_printTime;
int m_priority;
int m_retries;
int m_retryPause;
int m_threads;

View File

@ -22,29 +22,41 @@
*/
#include <stdlib.h>
#include <string.h>
#include <uv.h>
#include "net/Network.h"
#include "version.h"
#include "Platform.h"
char *Network::userAgent()
char *Platform::m_defaultConfigName = nullptr;
char *Platform::m_userAgent = nullptr;
const char *Platform::defaultConfigName()
{
const size_t max = 128;
size_t size = 520;
char *buf = static_cast<char*>(malloc(max));
int length = snprintf(buf, max, "%s/%s (Linux ", APP_NAME, APP_VERSION);
if (m_defaultConfigName == nullptr) {
m_defaultConfigName = new char[size];
}
# if defined(__x86_64__)
length += snprintf(buf + length, max - length, "x86_64) libuv/%s", uv_version_string());
# else
length += snprintf(buf + length, max - length, "i686) libuv/%s", uv_version_string());
# endif
if (uv_exepath(m_defaultConfigName, &size) < 0) {
return nullptr;
}
# ifdef __GNUC__
length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
# endif
if (size < 500) {
# ifdef WIN32
char *p = strrchr(m_defaultConfigName, '\\');
# else
char *p = strrchr(m_defaultConfigName, '/');
# endif
return buf;
if (p) {
strcpy(p + 1, "config.json");
return m_defaultConfigName;
}
}
return nullptr;
}

View File

@ -21,19 +21,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include "net/Network.h"
#include "version.h"
#ifndef __PLATFORM_H__
#define __PLATFORM_H__
char *Network::userAgent()
class Platform
{
const size_t max = 128;
public:
static const char *defaultConfigName();
static void init(const char *userAgent);
static void release();
static void setProcessPriority(int priority);
static void setThreadPriority(int priority);
char *buf = static_cast<char*>(malloc(max));
snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s clang/%d.%d.%d", APP_NAME, APP_VERSION, uv_version_string(), __clang_major__, __clang_minor__, __clang_patchlevel__);
static inline const char *userAgent() { return m_userAgent; }
return buf;
}
private:
static char *m_defaultConfigName;
static char *m_userAgent;
};
#endif /* __PLATFORM_H__ */

View File

@ -0,0 +1,108 @@
/* 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 <stdlib.h>
#include <sys/resource.h>
#include <uv.h>
#include "Platform.h"
#include "version.h"
#ifdef XMRIG_NVIDIA_PROJECT
# include "nvidia/cryptonight.h"
#endif
static inline char *createUserAgent()
{
const size_t max = 160;
char *buf = new char[max];
# ifdef XMRIG_NVIDIA_PROJECT
const int cudaVersion = cuda_get_runtime_version();
snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s CUDA/%d.%d clang/%d.%d.%d", APP_NAME, APP_VERSION, uv_version_string(), cudaVersion / 1000, cudaVersion % 100, __clang_major__, __clang_minor__, __clang_patchlevel__);
# else
snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s clang/%d.%d.%d", APP_NAME, APP_VERSION, uv_version_string(), __clang_major__, __clang_minor__, __clang_patchlevel__);
# endif
return buf;
}
void Platform::init(const char *userAgent)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
}
void Platform::release()
{
delete [] m_userAgent;
}
void Platform::setProcessPriority(int priority)
{
}
void Platform::setThreadPriority(int priority)
{
if (priority == -1) {
return;
}
int prio = 19;
switch (priority)
{
case 1:
prio = 5;
break;
case 2:
prio = 0;
break;
case 3:
prio = -5;
break;
case 4:
prio = -10;
break;
case 5:
prio = -15;
break;
default:
break;
}
setpriority(PRIO_PROCESS, 0, prio);
}

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 <sched.h>
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <uv.h>
#include "Platform.h"
#include "version.h"
#ifdef XMRIG_NVIDIA_PROJECT
# include "nvidia/cryptonight.h"
#endif
static inline char *createUserAgent()
{
const size_t max = 160;
char *buf = new char[max];
int length = snprintf(buf, max, "%s/%s (Linux ", APP_NAME, APP_VERSION);
# if defined(__x86_64__)
length += snprintf(buf + length, max - length, "x86_64) libuv/%s", uv_version_string());
# else
length += snprintf(buf + length, max - length, "i686) libuv/%s", uv_version_string());
# endif
# ifdef XMRIG_NVIDIA_PROJECT
const int cudaVersion = cuda_get_runtime_version();
length += snprintf(buf + length, max - length, " CUDA/%d.%d", cudaVersion / 1000, cudaVersion % 100);
# endif
# ifdef __GNUC__
length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
# endif
return buf;
}
void Platform::init(const char *userAgent)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
}
void Platform::release()
{
delete [] m_userAgent;
}
void Platform::setProcessPriority(int priority)
{
}
void Platform::setThreadPriority(int priority)
{
if (priority == -1) {
return;
}
int prio = 19;
switch (priority)
{
case 1:
prio = 5;
break;
case 2:
prio = 0;
break;
case 3:
prio = -5;
break;
case 4:
prio = -10;
break;
case 5:
prio = -15;
break;
default:
break;
}
setpriority(PRIO_PROCESS, 0, prio);
if (priority == 0) {
sched_param param;
param.sched_priority = 0;
if (sched_setscheduler(0, SCHED_IDLE, &param) != 0) {
sched_setscheduler(0, SCHED_BATCH, &param);
}
}
}

View File

@ -24,11 +24,16 @@
#include <winsock2.h>
#include <windows.h>
#include <uv.h>
#include "net/Network.h"
#include "Platform.h"
#include "version.h"
#ifdef XMRIG_NVIDIA_PROJECT
# include "nvidia/cryptonight.h"
#endif
static inline OSVERSIONINFOEX winOsVersion()
{
@ -48,12 +53,12 @@ static inline OSVERSIONINFOEX winOsVersion()
}
char *Network::userAgent()
static inline char *createUserAgent()
{
const auto osver = winOsVersion();
const size_t max = 128;
const size_t max = 160;
char *buf = static_cast<char*>(malloc(max));
char *buf = new char[max];
int length = snprintf(buf, max, "%s/%s (Windows NT %lu.%lu", APP_NAME, APP_VERSION, osver.dwMajorVersion, osver.dwMinorVersion);
# if defined(__x86_64__) || defined(_M_AMD64)
@ -62,6 +67,11 @@ char *Network::userAgent()
length += snprintf(buf + length, max - length, ") libuv/%s", uv_version_string());
# endif
# ifdef XMRIG_NVIDIA_PROJECT
const int cudaVersion = cuda_get_runtime_version();
length += snprintf(buf + length, max - length, " CUDA/%d.%d", cudaVersion / 1000, cudaVersion % 100);
# endif
# ifdef __GNUC__
length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
# elif _MSC_VER
@ -70,3 +80,91 @@ char *Network::userAgent()
return buf;
}
void Platform::init(const char *userAgent)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
}
void Platform::release()
{
delete [] m_defaultConfigName;
delete [] m_userAgent;
}
void Platform::setProcessPriority(int priority)
{
if (priority == -1) {
return;
}
DWORD prio = IDLE_PRIORITY_CLASS;
switch (priority)
{
case 1:
prio = BELOW_NORMAL_PRIORITY_CLASS;
break;
case 2:
prio = NORMAL_PRIORITY_CLASS;
break;
case 3:
prio = ABOVE_NORMAL_PRIORITY_CLASS;
break;
case 4:
prio = HIGH_PRIORITY_CLASS;
break;
case 5:
prio = REALTIME_PRIORITY_CLASS;
default:
break;
}
SetPriorityClass(GetCurrentProcess(), prio);
}
void Platform::setThreadPriority(int priority)
{
if (priority == -1) {
return;
}
int prio = THREAD_PRIORITY_IDLE;
switch (priority)
{
case 1:
prio = THREAD_PRIORITY_BELOW_NORMAL;
break;
case 2:
prio = THREAD_PRIORITY_NORMAL;
break;
case 3:
prio = THREAD_PRIORITY_ABOVE_NORMAL;
break;
case 4:
prio = THREAD_PRIORITY_HIGHEST;
break;
case 5:
prio = THREAD_PRIORITY_TIME_CRITICAL;
break;
default:
break;
}
SetThreadPriority(GetCurrentThread(), prio);
}

View File

@ -4,6 +4,7 @@
"background": false,
"colors": true,
"cpu-affinity": null,
"cpu-priority": null,
"donate-level": 5,
"log-file": null,
"max-cpu-usage": 75,

View File

@ -311,7 +311,7 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
template<size_t ITERATIONS, size_t MEM, size_t MASK, bool SOFT_AES>
inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, cryptonight_ctx *__restrict__ ctx)
{
keccak(static_cast<const uint8_t*>(input), size, ctx->state0, 200);
keccak(static_cast<const uint8_t*>(input), (int) size, ctx->state0, 200);
cn_explode_scratchpad<MEM, SOFT_AES>((__m128i*) ctx->state0, (__m128i*) ctx->memory);
@ -365,8 +365,8 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *
template<size_t ITERATIONS, size_t MEM, size_t MASK, bool SOFT_AES>
inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
{
keccak((const uint8_t *) input, size, ctx->state0, 200);
keccak((const uint8_t *) input + size, size, ctx->state1, 200);
keccak((const uint8_t *) input, (int) size, ctx->state0, 200);
keccak((const uint8_t *) input + size, (int) size, ctx->state1, 200);
const uint8_t* l0 = ctx->memory;
const uint8_t* l1 = ctx->memory + MEM;

View File

@ -148,7 +148,7 @@ void blake256_update(state *S, const uint8_t *data, uint64_t datalen) {
if (datalen > 0) {
memcpy((void *) (S->buf + left), (void *) data, datalen >> 3);
S->buflen = (left << 3) + datalen;
S->buflen = (left << 3) + (int) datalen;
} else {
S->buflen = 0;
}

View File

@ -41,6 +41,7 @@ public:
virtual void connect() = 0;
virtual void resume() = 0;
virtual void stop() = 0;
virtual void tick(uint64_t now) = 0;
};

View File

@ -40,7 +40,10 @@
ConsoleLog::ConsoleLog(bool colors) :
m_colors(colors)
{
uv_tty_init(uv_default_loop(), &m_tty, 1, 0);
if (uv_tty_init(uv_default_loop(), &m_tty, 1, 0) < 0) {
return;
}
uv_tty_set_mode(&m_tty, UV_TTY_MODE_NORMAL);
# ifdef WIN32
@ -58,6 +61,10 @@ ConsoleLog::ConsoleLog(bool colors) :
void ConsoleLog::message(int level, const char* fmt, va_list args)
{
if (!isWritable()) {
return;
}
time_t now = time(nullptr);
tm stime;
@ -92,8 +99,7 @@ void ConsoleLog::message(int level, const char* fmt, va_list args)
}
}
const size_t len = 64 + strlen(fmt) + 2;
char *buf = new char[len];
char *buf = new char[64 + strlen(fmt) + 2];
sprintf(buf, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n",
stime.tm_year + 1900,
@ -113,8 +119,11 @@ void ConsoleLog::message(int level, const char* fmt, va_list args)
void ConsoleLog::text(const char* fmt, va_list args)
{
const int len = 64 + strlen(fmt) + 2;
char *buf = new char[len];
if (!isWritable()) {
return;
}
char *buf = new char[64 + strlen(fmt) + 2];
sprintf(buf, "%s%s\n", fmt, m_colors ? Log::kCL_N : "");
@ -122,6 +131,12 @@ void ConsoleLog::text(const char* fmt, va_list args)
}
bool ConsoleLog::isWritable() const
{
return uv_is_writable(reinterpret_cast<const uv_stream_t*>(&m_tty)) == 1 && uv_guess_handle(1) == UV_TTY;
}
void ConsoleLog::print(char *fmt, va_list args)
{
vsnprintf(m_buf, sizeof(m_buf) - 1, fmt, args);

View File

@ -40,6 +40,7 @@ public:
void text(const char *fmt, va_list args) override;
private:
bool isWritable() const;
void print(char *fmt, va_list args);
bool m_colors;

View File

@ -88,7 +88,7 @@ void FileLog::onWrite(uv_fs_t *req)
void FileLog::write(char *data, size_t size)
{
uv_buf_t buf = uv_buf_init(data, size);
uv_buf_t buf = uv_buf_init(data, (unsigned int) size);
uv_fs_t *req = static_cast<uv_fs_t*>(malloc(sizeof(uv_fs_t)));
req->data = buf.base;

View File

@ -77,10 +77,14 @@ private:
#ifdef APP_DEBUG
# define LOG_DEBUG(x, ...) Log::i()->message(Log::DEBUG, x, ##__VA_ARGS__)
#else
# define LOG_DEBUG(x, ...)
#endif
#if defined(APP_DEBUG) || defined(APP_DEVEL)
# define LOG_DEBUG_ERR(x, ...) Log::i()->message(Log::ERR, x, ##__VA_ARGS__)
# define LOG_DEBUG_WARN(x, ...) Log::i()->message(Log::WARNING, x, ##__VA_ARGS__)
#else
# define LOG_DEBUG(x, ...)
# define LOG_DEBUG_ERR(x, ...)
# define LOG_DEBUG_WARN(x, ...)
#endif

View File

@ -56,13 +56,14 @@ Client::Client(int id, const char *agent, IClientListener *listener) :
m_failures(0),
m_recvBufPos(0),
m_state(UnconnectedState),
m_expire(0),
m_stream(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 = this;
m_hints.ai_family = PF_INET;
m_hints.ai_socktype = SOCK_STREAM;
@ -71,10 +72,10 @@ Client::Client(int id, const char *agent, IClientListener *listener) :
m_recvBuf.base = static_cast<char*>(malloc(kRecvBufSize));
m_recvBuf.len = kRecvBufSize;
auto loop = uv_default_loop();
uv_timer_init(loop, &m_retriesTimer);
uv_timer_init(loop, &m_responseTimer);
uv_timer_init(loop, &m_keepAliveTimer);
# ifndef XMRIG_PROXY_PROJECT
m_keepAliveTimer.data = this;
uv_timer_init(uv_default_loop(), &m_keepAliveTimer);
# endif
}
@ -93,12 +94,12 @@ Client::~Client()
int64_t Client::send(char *data, size_t size)
{
LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size ? size : strlen(data), data);
if (state() != ConnectedState) {
if (state() != ConnectedState || !uv_is_writable(m_stream)) {
LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state);
return -1;
}
uv_buf_t buf = uv_buf_init(data, size ? size : strlen(data));
uv_buf_t buf = uv_buf_init(data, (unsigned int) (size ? size : strlen(data)));
uv_write_t *req = new uv_write_t;
req->data = buf.base;
@ -108,8 +109,7 @@ int64_t Client::send(char *data, size_t size)
delete req;
});
uv_timer_start(&m_responseTimer, [](uv_timer_t *handle) { getClient(handle->data)->close(); }, kResponseTimeout, 0);
m_expire = uv_now(uv_default_loop()) + kResponseTimeout;
return m_sequence++;
}
@ -134,9 +134,11 @@ void Client::connect(const Url *url)
void Client::disconnect()
{
# ifndef XMRIG_PROXY_PROJECT
uv_timer_stop(&m_keepAliveTimer);
uv_timer_stop(&m_responseTimer);
uv_timer_stop(&m_retriesTimer);
# endif
m_expire = 0;
m_failures = -1;
close();
@ -153,6 +155,24 @@ void Client::setUrl(const Url *url)
}
void Client::tick(uint64_t now)
{
if (m_expire == 0 || now < m_expire) {
return;
}
if (m_state == ConnectedState) {
LOG_DEBUG_ERR("[%s:%u] timeout", m_url.host(), m_url.port());
close();
}
if (m_state == ConnectingState) {
connect();
}
}
int64_t Client::submit(const JobResult &result)
{
char *req = static_cast<char*>(malloc(345));
@ -179,6 +199,28 @@ int64_t Client::submit(const JobResult &result)
}
bool Client::isCriticalError(const char *message)
{
if (!message) {
return false;
}
if (strncasecmp(message, "Unauthenticated", 15) == 0) {
return true;
}
if (strncasecmp(message, "your IP is banned", 17) == 0) {
return true;
}
if (strncasecmp(message, "IP Address currently banned", 27) == 0) {
return true;
}
return false;
}
bool Client::parseJob(const json_t *params, int *code)
{
if (!json_is_object(params)) {
@ -231,6 +273,7 @@ int Client::resolve(const char *host)
{
setState(HostLookupState);
m_expire = 0;
m_recvBufPos = 0;
if (m_failures == -1) {
@ -384,7 +427,7 @@ void Client::parseResponse(int64_t id, const json_t *result, const json_t *error
LOG_ERR("[%s:%u] error: \"%s\", code: %" PRId64, m_url.host(), m_url.port(), message, json_integer_value(json_object_get(error, "code")));
}
if (id == 1 || (message && strncasecmp(message, "Unauthenticated", 15) == 0)) {
if (id == 1 || isCriticalError(message)) {
close();
}
@ -432,19 +475,20 @@ void Client::reconnect()
{
setState(ConnectingState);
uv_timer_stop(&m_responseTimer);
# ifndef XMRIG_PROXY_PROJECT
if (m_url.isKeepAlive()) {
uv_timer_stop(&m_keepAliveTimer);
}
# endif
if (m_failures == -1) {
return m_listener->onClose(this, -1);
}
m_failures++;
m_listener->onClose(this, m_failures);
m_listener->onClose(this, (int) m_failures);
uv_timer_start(&m_retriesTimer, [](uv_timer_t *handle) { getClient(handle->data)->connect(); }, m_retryPause, 0);
m_expire = uv_now(uv_default_loop()) + m_retryPause;
}
@ -462,12 +506,15 @@ void Client::setState(SocketState state)
void Client::startTimeout()
{
uv_timer_stop(&m_responseTimer);
m_expire = 0;
# ifndef XMRIG_PROXY_PROJECT
if (!m_url.isKeepAlive()) {
return;
}
uv_timer_start(&m_keepAliveTimer, [](uv_timer_t *handle) { getClient(handle->data)->ping(); }, kKeepAliveTimeout, 0);
# endif
}
@ -523,7 +570,7 @@ void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
auto client = getClient(stream->data);
if (nread < 0) {
if (nread != UV_EOF && !client->m_quiet) {
LOG_ERR("[%s:%u] read error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(nread));
LOG_ERR("[%s:%u] read error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror((int) nread));
}
return client->close();;

View File

@ -62,6 +62,7 @@ public:
void connect(const Url *url);
void disconnect();
void setUrl(const Url *url);
void tick(uint64_t now);
inline bool isReady() const { return m_state == ConnectedState && m_failures == 0; }
inline const char *host() const { return m_url.host(); }
@ -76,6 +77,7 @@ public:
private:
constexpr static size_t kRecvBufSize = 4096;
bool isCriticalError(const char *message);
bool parseJob(const json_t *params, int *code);
bool parseLogin(const json_t *result, int *code);
int resolve(const char *host);
@ -112,14 +114,16 @@ private:
SocketState m_state;
static int64_t m_sequence;
std::map<int64_t, SubmitResult> m_results;
uint64_t m_expire;
Url m_url;
uv_buf_t m_recvBuf;
uv_getaddrinfo_t m_resolver;
uv_stream_t *m_stream;
uv_tcp_t *m_socket;
# ifndef XMRIG_PROXY_PROJECT
uv_timer_t m_keepAliveTimer;
uv_timer_t m_responseTimer;
uv_timer_t m_retriesTimer;
# endif
};

View File

@ -82,7 +82,7 @@ bool Job::setBlob(const char *blob)
return false;
}
if (!fromHex(blob, m_size * 2, m_blob)) {
if (!fromHex(blob, (int) m_size * 2, m_blob)) {
return false;
}

View File

@ -42,11 +42,12 @@ public:
inline bool isNicehash() const { return m_nicehash; }
inline bool isValid() const { return m_size > 0 && m_diff > 0; }
inline const char *id() const { return m_id; }
inline const uint32_t *nonce() const { return reinterpret_cast<const uint32_t*>(m_blob + 39); }
inline const uint8_t *blob() const { return m_blob; }
inline int poolId() const { return m_poolId; }
inline size_t size() const { return m_size; }
inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); }
inline uint32_t diff() const { return m_diff; }
inline uint32_t size() const { return m_size; }
inline uint32_t diff() const { return (uint32_t) m_diff; }
inline uint64_t target() const { return m_target; }
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
@ -67,7 +68,7 @@ private:
int m_poolId;
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.
uint32_t m_size;
size_t m_size;
uint64_t m_diff;
uint64_t m_target;

View File

@ -43,6 +43,15 @@ public:
}
inline JobResult(const Job &job) : poolId(0), diff(0), nonce(0)
{
memcpy(jobId, job.id(), sizeof(jobId));
poolId = job.poolId();
diff = job.diff();
nonce = *job.nonce();
}
inline JobResult &operator=(const Job &job) {
memcpy(jobId, job.id(), sizeof(jobId));
poolId = job.poolId();

View File

@ -21,6 +21,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef _MSC_VER
#pragma warning(disable:4244)
#endif
#include <inttypes.h>
#include <memory>
@ -35,11 +38,11 @@
#include "net/strategies/SinglePoolStrategy.h"
#include "net/Url.h"
#include "Options.h"
#include "Platform.h"
#include "workers/Workers.h"
Network::Network(const Options *options) :
m_donateActive(false),
m_options(options),
m_donate(nullptr),
m_accepted(0),
@ -48,26 +51,29 @@ Network::Network(const Options *options) :
srand(time(0) ^ (uintptr_t) this);
Workers::setListener(this);
m_agent = userAgent();
const std::vector<Url*> &pools = options->pools();
if (pools.size() > 1) {
m_strategy = new FailoverStrategy(pools, m_agent, this);
m_strategy = new FailoverStrategy(pools, Platform::userAgent(), this);
}
else {
m_strategy = new SinglePoolStrategy(pools.front(), m_agent, this);
m_strategy = new SinglePoolStrategy(pools.front(), Platform::userAgent(), this);
}
if (m_options->donateLevel() > 0) {
m_donate = new DonateStrategy(m_agent, this);
m_donate = new DonateStrategy(Platform::userAgent(), this);
}
m_timer.data = this;
uv_timer_init(uv_default_loop(), &m_timer);
uv_timer_start(&m_timer, Network::onTick, kTickInterval, kTickInterval);
}
Network::~Network()
{
free(m_agent);
}
@ -164,3 +170,21 @@ void Network::setJob(Client *client, const Job &job)
Workers::setJob(job);
}
void Network::tick()
{
const uint64_t now = uv_now(uv_default_loop());
m_strategy->tick(now);
if (m_donate) {
m_donate->tick(now);
}
}
void Network::onTick(uv_timer_t *handle)
{
static_cast<Network*>(handle->data)->tick();
}

View File

@ -47,8 +47,6 @@ public:
void connect();
void stop();
static char *userAgent();
protected:
void onActive(Client *client) override;
void onJob(Client *client, const Job &job) override;
@ -57,15 +55,19 @@ protected:
void onResultAccepted(Client *client, int64_t seq, uint32_t diff, uint64_t ms, const char *error) override;
private:
void setJob(Client *client, const Job &job);
constexpr static int kTickInterval = 1 * 1000;
void setJob(Client *client, const Job &job);
void tick();
static void onTick(uv_timer_t *handle);
bool m_donateActive;
char *m_agent;
const Options *m_options;
IStrategy *m_donate;
IStrategy *m_strategy;
uint64_t m_accepted;
uint64_t m_rejected;
uv_timer_t m_timer;
};

View File

@ -121,7 +121,7 @@ bool Url::parse(const char *url)
memcpy(m_host, base, size - 1);
m_host[size - 1] = '\0';
m_port = strtol(port, nullptr, 10);
m_port = (uint16_t) strtol(port, nullptr, 10);
return true;
}

View File

@ -24,17 +24,31 @@
#include "interfaces/IStrategyListener.h"
#include "net/Client.h"
#include "net/Job.h"
#include "net/strategies/DonateStrategy.h"
#include "Options.h"
extern "C"
{
#include "crypto/c_keccak.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("fee.xmrig.com", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443, Options::i()->pools().front()->user(), nullptr, false, true);
uint8_t hash[200];
char userId[65] = { 0 };
const char *user = Options::i()->pools().front()->user();
keccak(reinterpret_cast<const uint8_t *>(user), static_cast<int>(strlen(user)), hash, sizeof(hash));
Job::toHex(hash, 32, userId);
Url *url = new Url("fee.xmrig.com", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443, userId, nullptr, false, true);
m_client = new Client(-1, agent, this);
m_client->setUrl(url);
@ -69,6 +83,12 @@ void DonateStrategy::stop()
}
void DonateStrategy::tick(uint64_t now)
{
m_client->tick(now);
}
void DonateStrategy::onClose(Client *client, int failures)
{
}

View File

@ -49,6 +49,7 @@ public:
int64_t submit(const JobResult &result) override;
void connect() override;
void stop() override;
void tick(uint64_t now) override;
protected:
void onClose(Client *client, int failures) override;

View File

@ -74,6 +74,14 @@ void FailoverStrategy::stop()
}
void FailoverStrategy::tick(uint64_t now)
{
for (Client *client : m_pools) {
client->tick(now);
}
}
void FailoverStrategy::onClose(Client *client, int failures)
{
if (failures == -1) {
@ -132,7 +140,7 @@ void FailoverStrategy::onResultAccepted(Client *client, int64_t seq, uint32_t di
void FailoverStrategy::add(const Url *url, const char *agent)
{
Client *client = new Client(m_pools.size(), agent, this);
Client *client = new Client((int) m_pools.size(), agent, this);
client->setUrl(url);
client->setRetryPause(Options::i()->retryPause() * 1000);

View File

@ -49,6 +49,7 @@ public:
void connect() override;
void resume() override;
void stop() override;
void tick(uint64_t now) override;
protected:
void onClose(Client *client, int failures) override;

View File

@ -66,6 +66,12 @@ void SinglePoolStrategy::stop()
}
void SinglePoolStrategy::tick(uint64_t now)
{
m_client->tick(now);
}
void SinglePoolStrategy::onClose(Client *client, int failures)
{
if (!isActive()) {

View File

@ -46,6 +46,7 @@ public:
void connect() override;
void resume() override;
void stop() override;
void tick(uint64_t now) override;
protected:
void onClose(Client *client, int failures) override;

View File

@ -27,14 +27,14 @@
#define APP_ID "xmrig"
#define APP_NAME "XMRig"
#define APP_DESC "Monero (XMR) CPU miner"
#define APP_VERSION "2.2.1"
#define APP_VERSION "2.3.0-dev"
#define APP_DOMAIN "xmrig.com"
#define APP_SITE "www.xmrig.com"
#define APP_COPYRIGHT "Copyright (C) 2016-2017 xmrig.com"
#define APP_VER_MAJOR 2
#define APP_VER_MINOR 2
#define APP_VER_BUILD 1
#define APP_VER_MINOR 3
#define APP_VER_BUILD 0
#define APP_VER_REV 0
#ifdef _MSC_VER

View File

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

View File

@ -35,10 +35,11 @@ class IWorker;
class Handle
{
public:
Handle(int threadId, int threads, int64_t affinity);
Handle(int threadId, int threads, int64_t affinity, int priority);
void join();
void start(void (*callback) (void *));
inline int priority() const { return m_priority; }
inline int threadId() const { return m_threadId; }
inline int threads() const { return m_threads; }
inline int64_t affinity() const { return m_affinity; }
@ -46,6 +47,7 @@ public:
inline void setWorker(IWorker *worker) { m_worker = worker; }
private:
int m_priority;
int m_threadId;
int m_threads;
int64_t m_affinity;

View File

@ -127,8 +127,8 @@ double Hashrate::calc(size_t threadId, size_t ms) const
}
double hashes, time;
hashes = lastestHashCnt - earliestHashCount;
time = lastestStamp - earliestStamp;
hashes = (double) lastestHashCnt - earliestHashCount;
time = (double) lastestStamp - earliestStamp;
time /= 1000.0;
return hashes / time;

View File

@ -26,6 +26,7 @@
#include "Cpu.h"
#include "Mem.h"
#include "Platform.h"
#include "workers/Handle.h"
#include "workers/Worker.h"
@ -42,6 +43,7 @@ Worker::Worker(Handle *handle) :
Cpu::setAffinity(m_id, handle->affinity());
}
Platform::setThreadPriority(handle->priority());
m_ctx = Mem::create(m_id);
}

View File

@ -98,7 +98,7 @@ void Workers::setJob(const Job &job)
}
void Workers::start(int64_t affinity)
void Workers::start(int64_t affinity, int priority)
{
const int threads = Mem::threads();
m_hashrate = new Hashrate(threads);
@ -114,7 +114,7 @@ void Workers::start(int64_t affinity)
uv_timer_start(&m_timer, Workers::onTick, 500, 500);
for (int i = 0; i < threads; ++i) {
Handle *handle = new Handle(i, threads, affinity);
Handle *handle = new Handle(i, threads, affinity, priority);
m_workers.push_back(handle);
handle->start(Workers::onReady);
}

View File

@ -46,7 +46,7 @@ public:
static void printHashrate(bool detail);
static void setEnabled(bool enabled);
static void setJob(const Job &job);
static void start(int64_t affinity);
static void start(int64_t affinity, int priority);
static void stop();
static void submit(const JobResult &result);