1
0
mirror of https://github.com/xmrig/xmrig.git synced 2025-12-11 17:32:47 -05:00

Compare commits

..

41 Commits

Author SHA1 Message Date
XMRig
7004a51ce6 v2.2.0 2017-08-02 20:08:41 +03:00
XMRig
3cc18d30de Merge branch 'dev' 2017-08-02 20:01:10 +03:00
xmrig
bd3665e111 Update CHANGELOG.md 2017-08-02 19:53:10 +03:00
XMRig
a680220d28 Fixed autoconf mode for AMD FX CPUs. 2017-08-02 18:59:24 +03:00
xmrig
2d1fdec618 Update CHANGELOG.md 2017-08-01 20:20:30 +03:00
XMRig
b1a2215829 Add missing port in config.json. 2017-08-01 19:34:36 +03:00
XMRig
eb5f7c6a7b #46 Simplify config parsing 2017-08-01 12:56:30 +03:00
XMRig
1bc23354d3 #46 Add support for default config. 2017-07-31 18:38:02 +03:00
XMRig
e6a72b2f78 #46 Added config file support. 2017-07-31 16:05:16 +03:00
XMRig
5bed17a8af Fix stop for FailoverStrategy. 2017-07-27 07:36:16 +03:00
XMRig
7b21749a19 Merge branch 'feature-async-console' into dev 2017-07-23 11:08:09 +03:00
XMRig
0b5587fd6a Add commands help. 2017-07-23 10:04:23 +03:00
XMRig
776f77a8d4 Added IConsoleListener 2017-07-23 09:36:30 +03:00
XMRig
583f45e2da Add Console class. 2017-07-23 08:35:26 +03:00
XMRig
9b474f239f Disable QuickEdit mode for Windows. 2017-07-23 07:38:57 +03:00
XMRig
9665ff15ae Use uv_tty for console output and remove legacy winansi. 2017-07-23 05:59:57 +03:00
xmrig
b6bf6d9bc9 Update CHANGELOG.md 2017-07-20 02:56:07 +03:00
XMRig
3d9be9484d Merge branch 'dev'
# Conflicts:
#	src/version.h
2017-07-20 00:54:03 +03:00
XMRig
35fd43a6b4 Changed donation address, new xmrig-proxy is coming soon. 2017-07-19 23:57:03 +03:00
xmrig
294453fdc1 Update CHANGELOG.md 2017-07-19 23:54:50 +03:00
XMRig
30a7f9f7f5 Backport crypto changes from Dead2 xmr-stak-cpu fork. 2017-07-19 21:02:38 +03:00
XMRig
8f38462bbe #40 Fix crash on Linux. 2017-07-19 04:28:59 +03:00
XMRig
ebf54c6d04 Fix warnings on Linux. 2017-07-18 22:38:38 +03:00
XMRig
d7659b5093 Fixed %lld and %llu related warnings. 2017-07-18 20:20:29 +03:00
XMRig
e00c568ae9 Fix OS X build. 2017-07-18 14:09:20 +03:00
XMRig
a3988374f0 Fixed graceful shutdown. 2017-07-18 05:20:36 +03:00
XMRig
9732636155 Fixed bug, login request was contain malformed JSON if username or password has some special characters for example \. 2017-07-18 01:49:04 +03:00
XMRig
986aee4297 Better support for Round Robin DNS, related https://github.com/fireice-uk/xmr-stak-cpu/pull/220 2017-07-17 23:35:36 +03:00
XMRig
66d3e96a1a Sync changes with upcoming xmrig-proxy project. 2017-07-17 21:57:03 +03:00
XMRig
9f4e1ee373 Update version. 2017-07-14 21:26:22 +03:00
xmrig
ff0c6b6365 Update CHANGELOG.md 2017-07-14 21:22:48 +03:00
XMRig
7397efaf6d Merge branch 'master' of github.com:xmrig/xmrig 2017-07-14 21:16:05 +03:00
XMRig
aadc15ce66 Ignore duplicated job received from pool, with warning message. 2017-07-14 21:06:08 +03:00
XMRig
ad7c925a1a Merge branch 'dev' 2017-07-14 20:54:32 +03:00
XMRig
57be6f94bb Small code cleanup. 2017-07-13 18:02:48 +03:00
xmrig
35b188762c Update README.md 2017-07-12 14:02:07 +03:00
XMRig
7c6e429854 Improved pause/resume mechanism. 2017-07-10 21:42:28 +03:00
XMRig
c15aefd968 Merge branch 'master' into dev 2017-07-10 18:53:39 +03:00
XMRig
4a712354f1 #28 Fixed Alpine Linux support. 2017-07-07 07:15:58 +03:00
XMRig
a66297bed8 Merge branch 'master' into dev 2017-07-06 09:36:16 +03:00
XMRig
68795137da Merge branch 'master' into dev 2017-07-04 14:56:40 +03:00
51 changed files with 1061 additions and 2094 deletions

View File

@@ -1,3 +1,21 @@
# v2.2.0
- [#46](https://github.com/xmrig/xmrig/issues/46) Restored config file support. Now possible use multiple config files and combine with command line options also added support for default config.
- Improved colors support on Windows, now used uv_tty, legacy code removed.
- QuickEdit Mode now disabled on Windows.
- Added interactive commands in console window:: **h**ashrate, **p**ause, **r**esume.
- Fixed autoconf mode for AMD FX CPUs.
# v2.1.0
- [#40](https://github.com/xmrig/xmrig/issues/40)
Improved miner shutdown, fixed crash on exit for Linux and OS X.
- Fixed, login request was contain malformed JSON if username or password has some special characters for example `\`.
- [#220](https://github.com/fireice-uk/xmr-stak-cpu/pull/220) Better support for Round Robin DNS, IP address now always chosen randomly instead of stuck on first one.
- Changed donation address, new [xmrig-proxy](https://github.com/xmrig/xmrig-proxy) is coming soon.
# v2.0.2
- Better deal with possible duplicate jobs from pool, show warning and ignore duplicates.
- For Windows builds libuv updated to version 1.13.1 and gcc to 7.1.0.
# v2.0.1 # v2.0.1
- [#27](https://github.com/xmrig/xmrig/issues/27) Fixed possibility crash on 32bit systems. - [#27](https://github.com/xmrig/xmrig/issues/27) Fixed possibility crash on 32bit systems.

View File

@@ -11,8 +11,10 @@ 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/IConsoleListener.h
src/interfaces/IJobResultListener.h src/interfaces/IJobResultListener.h
src/interfaces/ILogBackend.h src/interfaces/ILogBackend.h
src/interfaces/IStrategy.h src/interfaces/IStrategy.h
@@ -58,6 +60,7 @@ set(HEADERS_CRYPTO
set(SOURCES set(SOURCES
src/App.cpp src/App.cpp
src/Console.cpp
src/log/ConsoleLog.cpp src/log/ConsoleLog.cpp
src/log/FileLog.cpp src/log/FileLog.cpp
src/log/Log.cpp src/log/Log.cpp
@@ -65,10 +68,10 @@ set(SOURCES
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/strategies/DonateStrategy.cpp src/net/strategies/DonateStrategy.cpp
src/net/strategies/FailoverStrategy.cpp src/net/strategies/FailoverStrategy.cpp
src/net/strategies/SinglePoolStrategy.cpp src/net/strategies/SinglePoolStrategy.cpp
src/net/Url.cpp
src/Options.cpp src/Options.cpp
src/Summary.cpp src/Summary.cpp
src/workers/DoubleWorker.cpp src/workers/DoubleWorker.cpp
@@ -94,8 +97,6 @@ set(SOURCES_CRYPTO
if (WIN32) if (WIN32)
set(SOURCES_OS set(SOURCES_OS
res/app.rc res/app.rc
src/3rdparty/winansi.cpp
src/3rdparty/winansi.h
src/App_win.cpp src/App_win.cpp
src/Cpu_win.cpp src/Cpu_win.cpp
src/Mem_win.cpp src/Mem_win.cpp
@@ -145,6 +146,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
if (WIN32) if (WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
add_definitions(/D__STDC_FORMAT_MACROS)
else() else()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
endif() endif()

View File

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

View File

@@ -1,392 +0,0 @@
/**
* Old Git implementation of windows terminal colors (2009)
* before use of a threaded wrapper.
*/
#undef NOGDI
#include <windows.h>
#include <wingdi.h>
#include <winreg.h>
#include <malloc.h>
#include <stdio.h>
#include <io.h>
#include "winansi.h"
/*
* Copyright 2008 Peter Harris <git@peter.is-a-geek.org>
*/
/*
Functions to be wrapped:
*/
#undef printf
#undef fprintf
#undef fputs
#undef vfprintf
/* TODO: write */
/*
ANSI codes used by git: m, K
This file is git-specific. Therefore, this file does not attempt
to implement any codes that are not used by git.
*/
static HANDLE console;
static WORD plain_attr;
static WORD attr;
static int negative;
static void init(void)
{
CONSOLE_SCREEN_BUFFER_INFO sbi;
static int initialized = 0;
if (initialized)
return;
console = GetStdHandle(STD_OUTPUT_HANDLE);
if (console == INVALID_HANDLE_VALUE)
console = NULL;
if (!console)
return;
GetConsoleScreenBufferInfo(console, &sbi);
attr = plain_attr = sbi.wAttributes;
negative = 0;
initialized = 1;
}
static int write_console(const char *str, int len)
{
/* convert utf-8 to utf-16, write directly to console */
int wlen = MultiByteToWideChar(CP_UTF8, 0, str, len, NULL, 0);
wchar_t *wbuf = (wchar_t *)alloca(wlen * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, str, len, wbuf, wlen);
WriteConsoleW(console, wbuf, wlen, NULL, NULL);
/* return original (utf-8 encoded) length */
return len;
}
#define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
static void set_console_attr(void)
{
WORD attributes = attr;
if (negative) {
attributes &= ~FOREGROUND_ALL;
attributes &= ~BACKGROUND_ALL;
/* This could probably use a bitmask
instead of a series of ifs */
if (attr & FOREGROUND_RED)
attributes |= BACKGROUND_RED;
if (attr & FOREGROUND_GREEN)
attributes |= BACKGROUND_GREEN;
if (attr & FOREGROUND_BLUE)
attributes |= BACKGROUND_BLUE;
if (attr & BACKGROUND_RED)
attributes |= FOREGROUND_RED;
if (attr & BACKGROUND_GREEN)
attributes |= FOREGROUND_GREEN;
if (attr & BACKGROUND_BLUE)
attributes |= FOREGROUND_BLUE;
}
SetConsoleTextAttribute(console, attributes);
}
static void erase_in_line(void)
{
CONSOLE_SCREEN_BUFFER_INFO sbi;
DWORD dummy; /* Needed for Windows 7 (or Vista) regression */
if (!console)
return;
GetConsoleScreenBufferInfo(console, &sbi);
FillConsoleOutputCharacterA(console, ' ',
sbi.dwSize.X - sbi.dwCursorPosition.X, sbi.dwCursorPosition,
&dummy);
}
static const char *set_attr(const char *str)
{
const char *func;
size_t len = strspn(str, "0123456789;");
func = str + len;
switch (*func) {
case 'm':
do {
long val = strtol(str, (char **)&str, 10);
switch (val) {
case 0: /* reset */
attr = plain_attr;
negative = 0;
break;
case 1: /* bold */
attr |= FOREGROUND_INTENSITY;
break;
case 2: /* faint */
case 22: /* normal */
attr &= ~FOREGROUND_INTENSITY;
break;
case 3: /* italic */
/* Unsupported */
break;
case 4: /* underline */
case 21: /* double underline */
/* Wikipedia says this flag does nothing */
/* Furthermore, mingw doesn't define this flag
attr |= COMMON_LVB_UNDERSCORE; */
break;
case 24: /* no underline */
/* attr &= ~COMMON_LVB_UNDERSCORE; */
break;
case 5: /* slow blink */
case 6: /* fast blink */
/* We don't have blink, but we do have
background intensity */
attr |= BACKGROUND_INTENSITY;
break;
case 25: /* no blink */
attr &= ~BACKGROUND_INTENSITY;
break;
case 7: /* negative */
negative = 1;
break;
case 27: /* positive */
negative = 0;
break;
case 8: /* conceal */
case 28: /* reveal */
/* Unsupported */
break;
case 30: /* Black */
attr &= ~FOREGROUND_ALL;
break;
case 31: /* Red */
attr &= ~FOREGROUND_ALL;
attr |= FOREGROUND_RED;
break;
case 32: /* Green */
attr &= ~FOREGROUND_ALL;
attr |= FOREGROUND_GREEN;
break;
case 33: /* Yellow */
attr &= ~FOREGROUND_ALL;
attr |= FOREGROUND_RED | FOREGROUND_GREEN;
break;
case 34: /* Blue */
attr &= ~FOREGROUND_ALL;
attr |= FOREGROUND_BLUE;
break;
case 35: /* Magenta */
attr &= ~FOREGROUND_ALL;
attr |= FOREGROUND_RED | FOREGROUND_BLUE;
break;
case 36: /* Cyan */
attr &= ~FOREGROUND_ALL;
attr |= FOREGROUND_GREEN | FOREGROUND_BLUE;
break;
case 37: /* White */
attr |= FOREGROUND_RED |
FOREGROUND_GREEN |
FOREGROUND_BLUE;
break;
case 38: /* Unknown */
break;
case 39: /* reset */
attr &= ~FOREGROUND_ALL;
attr |= (plain_attr & FOREGROUND_ALL);
break;
case 40: /* Black */
attr &= ~BACKGROUND_ALL;
break;
case 41: /* Red */
attr &= ~BACKGROUND_ALL;
attr |= BACKGROUND_RED;
break;
case 42: /* Green */
attr &= ~BACKGROUND_ALL;
attr |= BACKGROUND_GREEN;
break;
case 43: /* Yellow */
attr &= ~BACKGROUND_ALL;
attr |= BACKGROUND_RED | BACKGROUND_GREEN;
break;
case 44: /* Blue */
attr &= ~BACKGROUND_ALL;
attr |= BACKGROUND_BLUE;
break;
case 45: /* Magenta */
attr &= ~BACKGROUND_ALL;
attr |= BACKGROUND_RED | BACKGROUND_BLUE;
break;
case 46: /* Cyan */
attr &= ~BACKGROUND_ALL;
attr |= BACKGROUND_GREEN | BACKGROUND_BLUE;
break;
case 47: /* White */
attr |= BACKGROUND_RED |
BACKGROUND_GREEN |
BACKGROUND_BLUE;
break;
case 48: /* Unknown */
break;
case 49: /* reset */
attr &= ~BACKGROUND_ALL;
attr |= (plain_attr & BACKGROUND_ALL);
break;
default:
/* Unsupported code */
break;
}
str++;
} while (*(str - 1) == ';');
set_console_attr();
break;
case 'K':
erase_in_line();
break;
default:
/* Unsupported code */
break;
}
return func + 1;
}
static int ansi_emulate(const char *str, FILE *stream)
{
int rv = 0;
const char *pos = str;
fflush(stream);
while (*pos) {
pos = strstr(str, "\033[");
if (pos) {
int len = (int) (pos - str);
if (len) {
int out_len = write_console(str, len);
rv += out_len;
if (out_len < len)
return rv;
}
str = pos + 2;
rv += 2;
pos = set_attr(str);
rv += (int) (pos - str);
str = pos;
}
else {
int len = (int) strlen(str);
rv += write_console(str, len);
return rv;
}
}
return rv;
}
int winansi_fputs(const char *str, FILE *stream)
{
int rv;
if (!isatty(fileno(stream)))
return fputs(str, stream);
init();
if (!console)
return fputs(str, stream);
rv = ansi_emulate(str, stream);
if (rv >= 0)
return 0;
else
return EOF;
}
int winansi_vfprintf(FILE *stream, const char *format, va_list list)
{
int len, rv;
char small_buf[256] = { 0 };
char *buf = small_buf;
va_list cp;
if (!isatty(fileno(stream)))
goto abort;
init();
if (!console)
goto abort;
va_copy(cp, list);
len = vsnprintf(small_buf, sizeof(small_buf), format, cp);
#ifdef WIN32
/* bug on long strings without that */
if (len == -1)
len = _vscprintf(format, cp);
#endif
va_end(cp);
if ((unsigned) len > sizeof(small_buf) - 1) {
buf = (char*)malloc(len + 1);
if (!buf)
goto abort;
len = vsnprintf(buf, len + 1, format, list);
#ifdef WIN32
if (len == -1)
len = _vscprintf(format, list);
#endif
}
rv = ansi_emulate(buf, stream);
if (buf != small_buf)
free(buf);
return rv;
abort:
rv = vfprintf(stream, format, list);
return rv;
}
int winansi_fprintf(FILE *stream, const char *format, ...)
{
va_list list;
int rv;
va_start(list, format);
rv = winansi_vfprintf(stream, format, list);
va_end(list);
return rv;
}
int winansi_printf(const char *format, ...)
{
va_list list;
int rv;
va_start(list, format);
rv = winansi_vfprintf(stdout, format, list);
va_end(list);
return rv;
}

View File

@@ -1,29 +0,0 @@
/*
* ANSI emulation wrappers
*/
#include <windows.h>
#include <stddef.h>
#include <stdio.h>
#define fileno(fd) _fileno(fd)
#ifdef __cplusplus
extern "C" {
#endif
int winansi_fputs(const char *str, FILE *stream);
int winansi_printf(const char *format, ...);
int winansi_fprintf(FILE *stream, const char *format, ...);
int winansi_vfprintf(FILE *stream, const char *format, va_list list);
#ifdef __cplusplus
}
#endif
#undef fputs
#undef fprintf
#undef vfprintf
#define fputs winansi_fputs
#define printf winansi_printf
#define fprintf winansi_fprintf
#define vfprintf winansi_vfprintf

View File

@@ -27,6 +27,7 @@
#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/ConsoleLog.h"
@@ -50,6 +51,7 @@ App *App::m_self = nullptr;
App::App(int argc, char **argv) : App::App(int argc, char **argv) :
m_console(nullptr),
m_network(nullptr), m_network(nullptr),
m_options(nullptr) m_options(nullptr)
{ {
@@ -62,6 +64,7 @@ App::App(int argc, char **argv) :
if (!m_options->background()) { if (!m_options->background()) {
Log::add(new ConsoleLog(m_options->colors())); Log::add(new ConsoleLog(m_options->colors()));
m_console = new Console(this);
} }
if (m_options->logFile()) { if (m_options->logFile()) {
@@ -82,6 +85,7 @@ App::App(int argc, char **argv) :
App::~App() App::~App()
{ {
delete m_console;
} }
@@ -121,8 +125,44 @@ int App::exec()
} }
void App::onConsoleCommand(char command)
{
switch (command) {
case 'h':
case 'H':
Workers::printHashrate(true);
break;
case 'p':
case 'P':
LOG_INFO(m_options->colors() ? "\x1B[01;33mpaused\x1B[0m, press \x1B[01;35mr\x1B[0m to resume" : "paused, press 'r' to resume");
Workers::setEnabled(false);
break;
case 'r':
case 'R':
if (!Workers::isEnabled()) {
LOG_INFO(m_options->colors() ? "\x1B[01;32mresumed" : "resumed");
Workers::setEnabled(true);
}
break;
case 3:
LOG_WARN("Ctrl+C received, exiting");
close();
break;
default:
break;
}
}
void App::close() void App::close()
{ {
m_network->stop();
Workers::stop();
uv_stop(uv_default_loop()); uv_stop(uv_default_loop());
} }
@@ -147,5 +187,6 @@ void App::onSignal(uv_signal_t *handle, int signum)
break; break;
} }
uv_signal_stop(handle);
m_self->close(); m_self->close();
} }

View File

@@ -28,11 +28,15 @@
#include <uv.h> #include <uv.h>
#include "interfaces/IConsoleListener.h"
class Console;
class Network; class Network;
class Options; class Options;
class App class App : public IConsoleListener
{ {
public: public:
App(int argc, char **argv); App(int argc, char **argv);
@@ -40,6 +44,9 @@ public:
int exec(); int exec();
protected:
void onConsoleCommand(char command) override;
private: private:
void background(); void background();
void close(); void close();
@@ -48,6 +55,7 @@ private:
static App *m_self; static App *m_self;
Console *m_console;
Network *m_network; Network *m_network;
Options *m_options; Options *m_options;
uv_signal_t m_signal; uv_signal_t m_signal;

57
src/Console.cpp Normal file
View File

@@ -0,0 +1,57 @@
/* 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 "Console.h"
#include "interfaces/IConsoleListener.h"
Console::Console(IConsoleListener *listener)
: m_listener(listener)
{
m_tty.data = this;
uv_tty_init(uv_default_loop(), &m_tty, 0, 1);
uv_tty_set_mode(&m_tty, UV_TTY_MODE_RAW);
uv_read_start(reinterpret_cast<uv_stream_t*>(&m_tty), Console::onAllocBuffer, Console::onRead);
}
void Console::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
{
auto console = static_cast<Console*>(handle->data);
buf->len = 1;
buf->base = console->m_buf;
}
void Console::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
{
if (nread < 0) {
return uv_close(reinterpret_cast<uv_handle_t*>(stream), nullptr);
}
if (nread == 1) {
static_cast<Console*>(stream->data)->m_listener->onConsoleCommand(buf->base[0]);
}
}

49
src/Console.h Normal file
View File

@@ -0,0 +1,49 @@
/* 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 __CONSOLE_H__
#define __CONSOLE_H__
#include <uv.h>
class IConsoleListener;
class Console
{
public:
Console(IConsoleListener *listener);
private:
static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf);
char m_buf[1];
IConsoleListener *m_listener;
uv_tty_t m_tty;
};
#endif /* __CONSOLE_H__ */

View File

@@ -29,13 +29,14 @@
#include "Cpu.h" #include "Cpu.h"
char Cpu::m_brand[64] = { 0 }; bool Cpu::m_l2_exclusive = false;
int Cpu::m_flags = 0; char Cpu::m_brand[64] = { 0 };
int Cpu::m_l2_cache = 0; int Cpu::m_flags = 0;
int Cpu::m_l3_cache = 0; int Cpu::m_l2_cache = 0;
int Cpu::m_sockets = 1; int Cpu::m_l3_cache = 0;
int Cpu::m_totalCores = 0; int Cpu::m_sockets = 1;
int Cpu::m_totalThreads = 0; int Cpu::m_totalCores = 0;
int Cpu::m_totalThreads = 0;
int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage) int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage)
@@ -44,7 +45,14 @@ int Cpu::optimalThreadsCount(int algo, bool doubleHash, int maxCpuUsage)
return 1; return 1;
} }
int cache = m_l3_cache ? m_l3_cache : m_l2_cache; int cache = 0;
if (m_l3_cache) {
cache = m_l2_exclusive ? (m_l2_cache + m_l3_cache) : m_l3_cache;
}
else {
cache = m_l2_cache;
}
int count = 0; int count = 0;
const int size = (algo ? 1024 : 2048) * (doubleHash ? 2 : 1); const int size = (algo ? 1024 : 2048) * (doubleHash ? 2 : 1);
@@ -84,8 +92,9 @@ void Cpu::initCommon()
m_l3_cache = data.l3_cache > 0 ? data.l3_cache * m_sockets : 0; m_l3_cache = data.l3_cache > 0 ? data.l3_cache * m_sockets : 0;
// Workaround for AMD CPUs https://github.com/anrieff/libcpuid/issues/97 // Workaround for AMD CPUs https://github.com/anrieff/libcpuid/issues/97
if (data.vendor == VENDOR_AMD && data.l3_cache <= 0 && data.l2_assoc == 16 && data.ext_family >= 21) { if (data.vendor == VENDOR_AMD && data.ext_family >= 0x15 && data.ext_family < 0x17) {
m_l2_cache = data.l2_cache * (m_totalCores / 2) * m_sockets; m_l2_cache = data.l2_cache * (m_totalCores / 2) * m_sockets;
m_l2_exclusive = true;
} }
else { else {
m_l2_cache = data.l2_cache > 0 ? data.l2_cache * m_totalCores * m_sockets : 0; m_l2_cache = data.l2_cache > 0 ? data.l2_cache * m_totalCores * m_sockets : 0;

View File

@@ -53,6 +53,7 @@ public:
private: private:
static void initCommon(); static void initCommon();
static bool m_l2_exclusive;
static char m_brand[64]; static char m_brand[64];
static int m_flags; static int m_flags;
static int m_l2_cache; static int m_l2_cache;

View File

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

View File

@@ -113,6 +113,36 @@ static struct option const options[] = {
}; };
static struct option const config_options[] = {
{ "algo", 1, nullptr, 'a' },
{ "av", 1, nullptr, 'v' },
{ "background", 0, nullptr, 'B' },
{ "cpu-affinity", 1, nullptr, 1020 },
{ "donate-level", 1, nullptr, 1003 },
{ "log-file", 1, nullptr, 'l' },
{ "max-cpu-usage", 1, nullptr, 1004 },
{ "print-time", 1, nullptr, 1007 },
{ "retries", 1, nullptr, 'r' },
{ "retry-pause", 1, nullptr, 'R' },
{ "safe", 0, nullptr, 1005 },
{ "syslog", 0, nullptr, 'S' },
{ "threads", 1, nullptr, 't' },
{ "colors", 0, nullptr, 2000 },
{ 0, 0, 0, 0 }
};
static struct option const pool_options[] = {
{ "url", 1, nullptr, 'o' },
{ "pass", 1, nullptr, 'p' },
{ "user", 1, nullptr, 'u' },
{ "userpass", 1, nullptr, 'O' },
{ "keepalive", 0, nullptr ,'k' },
{ "nicehash", 0, nullptr, 1006 },
{ 0, 0, 0, 0 }
};
static const char *algo_names[] = { static const char *algo_names[] = {
"cryptonight", "cryptonight",
# ifndef XMRIG_NO_AEON # ifndef XMRIG_NO_AEON
@@ -121,6 +151,34 @@ 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::parse(int argc, char **argv)
{ {
if (!m_self) { if (!m_self) {
@@ -176,7 +234,13 @@ Options::Options(int argc, char **argv) :
} }
if (!m_pools[0]->isValid()) { if (!m_pools[0]->isValid()) {
fprintf(stderr, "No pool URL supplied. Exiting."); char *fileName = defaultConfigName();
parseConfig(fileName);
delete [] fileName;
}
if (!m_pools[0]->isValid()) {
fprintf(stderr, "No pool URL supplied. Exiting.\n");
return; return;
} }
@@ -204,11 +268,8 @@ Options::~Options()
} }
bool Options::parseArg(int key, char *arg) bool Options::parseArg(int key, const char *arg)
{ {
char *p;
int v;
switch (key) { switch (key) {
case 'a': /* --algo */ case 'a': /* --algo */
if (!setAlgo(arg)) { if (!setAlgo(arg)) {
@@ -216,13 +277,6 @@ bool Options::parseArg(int key, char *arg)
} }
break; break;
case 'O': /* --userpass */
if (!m_pools.back()->setUserpass(arg)) {
return false;
}
break;
case 'o': /* --url */ case 'o': /* --url */
if (m_pools.size() > 1 || m_pools[0]->isValid()) { if (m_pools.size() > 1 || m_pools[0]->isValid()) {
Url *url = new Url(arg); Url *url = new Url(arg);
@@ -240,7 +294,12 @@ bool Options::parseArg(int key, char *arg)
if (!m_pools.back()->isValid()) { if (!m_pools.back()->isValid()) {
return false; return false;
} }
break;
case 'O': /* --userpass */
if (!m_pools.back()->setUserpass(arg)) {
return false;
}
break; break;
case 'u': /* --user */ case 'u': /* --user */
@@ -257,53 +316,22 @@ bool Options::parseArg(int key, char *arg)
m_colors = false; m_colors = false;
break; break;
case 'r': /* --retries */ case 'r': /* --retries */
v = strtol(arg, nullptr, 10); case 'R': /* --retry-pause */
if (v < 1 || v > 1000) { case 't': /* --threads */
showUsage(1); case 'v': /* --av */
return false; case 1003: /* --donate-level */
}
m_retries = v;
break;
case 'R': /* --retry-pause */
v = strtol(arg, nullptr, 10);
if (v < 1 || v > 3600) {
showUsage(1);
return false;
}
m_retryPause = v;
break;
case 't': /* --threads */
v = strtol(arg, nullptr, 10);
if (v < 1 || v > 1024) {
showUsage(1);
return false;
}
m_threads = v;
break;
case 1004: /* --max-cpu-usage */ case 1004: /* --max-cpu-usage */
v = strtol(arg, nullptr, 10); case 1007: /* --print-time */
if (v < 1 || v > 100) { return parseArg(key, strtol(arg, nullptr, 10));
showUsage(1);
return false;
}
m_maxCpuUsage = v;
break;
case 'B': /* --background */
case 'k': /* --keepalive */
case 'S': /* --syslog */
case 1002: /* --no-color */
case 1005: /* --safe */ case 1005: /* --safe */
m_safe = true; case 1006: /* --nicehash */
break; return parseBoolean(key, true);
case 'k': /* --keepalive */
m_pools.back()->setKeepAlive(true);
break;
case 'V': /* --version */ case 'V': /* --version */
showVersion(); showVersion();
@@ -313,59 +341,15 @@ bool Options::parseArg(int key, char *arg)
showUsage(0); showUsage(0);
return false; return false;
case 'B': /* --background */ case 'c': /* --config */
m_background = true; parseConfig(arg);
m_colors = false;
break; break;
case 'S': /* --syslog */ case 1020: { /* --cpu-affinity */
m_syslog = true; const char *p = strstr(arg, "0x");
m_colors = false; return parseArg(key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10));
break;
case 'v': /* --av */
v = strtol(arg, nullptr, 10);
if (v < 0 || v > 1000) {
showUsage(1);
return false;
} }
m_algoVariant = v;
break;
case 1020: /* --cpu-affinity */
p = strstr(arg, "0x");
m_affinity = p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10);
break;
case 1002: /* --no-color */
m_colors = false;
break;
case 1003: /* --donate-level */
v = strtol(arg, nullptr, 10);
if (v < 1 || v > 99) {
showUsage(1);
return false;
}
m_donateLevel = v;
break;
case 1006: /* --nicehash */
m_pools.back()->setNicehash(true);
break;
case 1007: /* --print-time */
v = strtol(arg, nullptr, 10);
if (v < 0 || v > 1000) {
showUsage(1);
return false;
}
m_printTime = v;
break;
default: default:
showUsage(1); showUsage(1);
return false; return false;
@@ -375,6 +359,127 @@ bool Options::parseArg(int key, char *arg)
} }
bool Options::parseArg(int key, uint64_t arg)
{
switch (key) {
case 'r': /* --retries */
if (arg < 1 || arg > 1000) {
showUsage(1);
return false;
}
m_retries = arg;
break;
case 'R': /* --retry-pause */
if (arg < 1 || arg > 3600) {
showUsage(1);
return false;
}
m_retryPause = arg;
break;
case 't': /* --threads */
if (arg < 1 || arg > 1024) {
showUsage(1);
return false;
}
m_threads = arg;
break;
case 'v': /* --av */
if (arg > 1000) {
showUsage(1);
return false;
}
m_algoVariant = arg;
break;
case 1003: /* --donate-level */
if (arg < 1 || arg > 99) {
showUsage(1);
return false;
}
m_donateLevel = arg;
break;
case 1004: /* --max-cpu-usage */
if (arg < 1 || arg > 100) {
showUsage(1);
return false;
}
m_maxCpuUsage = arg;
break;
case 1007: /* --print-time */
if (arg > 1000) {
showUsage(1);
return false;
}
m_printTime = arg;
break;
case 1020: /* --cpu-affinity */
if (arg) {
m_affinity = arg;
}
break;
default:
break;
}
return true;
}
bool Options::parseBoolean(int key, bool enable)
{
switch (key) {
case 'k': /* --keepalive */
m_pools.back()->setKeepAlive(enable);
break;
case 'B': /* --background */
m_background = enable;
m_colors = enable ? false : m_colors;
break;
case 'S': /* --syslog */
m_syslog = enable;
m_colors = enable ? false : m_colors;
break;
case 1002: /* --no-color */
m_colors = enable;
break;
case 1005: /* --safe */
m_safe = enable;
break;
case 1006: /* --nicehash */
m_pools.back()->setNicehash(enable);
break;
case 2000: /* colors */
m_colors = enable;
break;
default:
break;
}
return true;
}
Url *Options::parseUrl(const char *arg) const Url *Options::parseUrl(const char *arg) const
{ {
auto url = new Url(arg); auto url = new Url(arg);
@@ -387,6 +492,72 @@ Url *Options::parseUrl(const char *arg) const
} }
void Options::parseConfig(const char *fileName)
{
json_error_t err;
json_t *config = json_load_file(fileName, 0, &err);
if (!json_is_object(config)) {
if (config) {
json_decref(config);
return;
}
if (err.line < 0) {
fprintf(stderr, "%s\n", err.text);
}
else {
fprintf(stderr, "%s:%d: %s\n", fileName, err.line, err.text);
}
return;
}
for (size_t i = 0; i < ARRAY_SIZE(config_options); i++) {
parseJSON(&config_options[i], config);
}
json_t *pools = json_object_get(config, "pools");
if (json_is_array(pools)) {
size_t index;
json_t *value;
json_array_foreach(pools, index, value) {
if (json_is_object(value)) {
for (size_t i = 0; i < ARRAY_SIZE(pool_options); i++) {
parseJSON(&pool_options[i], value);
}
}
}
}
json_decref(config);
}
void Options::parseJSON(const struct option *option, json_t *object)
{
if (!option->name) {
return;
}
json_t *val = json_object_get(object, option->name);
if (!val) {
return;
}
if (option->has_arg && json_is_string(val)) {
parseArg(option->val, json_string_value(val));
}
else if (option->has_arg && json_is_integer(val)) {
parseArg(option->val, json_integer_value(val));
}
else if (!option->has_arg && json_is_boolean(val)) {
parseBoolean(option->val, json_is_true(val));
}
}
void Options::showUsage(int status) const void Options::showUsage(int status) const
{ {
if (status) { if (status) {

View File

@@ -25,11 +25,13 @@
#define __OPTIONS_H__ #define __OPTIONS_H__
#include <vector> #include <jansson.h>
#include <stdint.h> #include <stdint.h>
#include <vector>
class Url; class Url;
struct option;
class Options class Options
@@ -76,8 +78,12 @@ private:
static Options *m_self; static Options *m_self;
bool parseArg(int key, char *arg); bool parseArg(int key, const char *arg);
bool parseArg(int key, uint64_t arg);
bool parseBoolean(int key, bool enable);
Url *parseUrl(const char *arg) const; Url *parseUrl(const char *arg) const;
void parseConfig(const char *fileName);
void parseJSON(const struct option *option, json_t *object);
void showUsage(int status) const; void showUsage(int status) const;
void showVersion(void); void showVersion(void);

View File

@@ -22,6 +22,7 @@
*/ */
#include <inttypes.h>
#include <uv.h> #include <uv.h>
@@ -49,11 +50,8 @@ static void print_versions()
# endif # endif
if (Options::i()->colors()) { Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mVERSIONS: \x1B[01;36mXMRig/%s\x1B[01;37m libuv/%s%s" : " * VERSIONS: XMRig/%s libuv/%s%s",
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); APP_VERSION, uv_version_string(), buf);
} else {
Log::i()->text(" * VERSIONS: XMRig/%s libuv/%s%s", APP_VERSION, uv_version_string(), buf);
}
} }
@@ -94,7 +92,7 @@ static void print_threads()
{ {
char buf[32]; char buf[32];
if (Options::i()->affinity() != -1L) { if (Options::i()->affinity() != -1L) {
snprintf(buf, 32, ", affinity=0x%llX", Options::i()->affinity()); snprintf(buf, 32, ", affinity=0x%" PRIX64, Options::i()->affinity());
} }
else { else {
buf[0] = '\0'; buf[0] = '\0';
@@ -129,6 +127,17 @@ static void print_pools()
} }
static void print_commands()
{
if (Options::i()->colors()) {
Log::i()->text("\x1B[01;32m * \x1B[01;37mCOMMANDS: \x1B[01;35mh\x1B[01;37mashrate, \x1B[01;35mp\x1B[01;37mause, \x1B[01;35mr\x1B[01;37mesume");
}
else {
Log::i()->text(" * COMMANDS: 'h' hashrate, 'p' pause, 'r' resume");
}
}
void Summary::print() void Summary::print()
{ {
print_versions(); print_versions();
@@ -136,6 +145,7 @@ void Summary::print()
print_cpu(); print_cpu();
print_threads(); print_threads();
print_pools(); print_pools();
print_commands();
} }

25
src/config.json Normal file
View File

@@ -0,0 +1,25 @@
{
"algo": "cryptonight",
"av": 0,
"background": false,
"colors": true,
"cpu-affinity": null,
"donate-level": 5,
"log-file": null,
"max-cpu-usage": 75,
"print-time": 60,
"retries": 5,
"retry-pause": 5,
"safe": false,
"syslog": false,
"threads": null,
"pools": [
{
"url": "pool.minemonero.pro:5555",
"user": "",
"pass": "x",
"keepalive": true,
"nicehash": false
}
]
}

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@@ -0,0 +1,37 @@
/* 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 __ICONSOLELISTENER_H__
#define __ICONSOLELISTENER_H__
class IConsoleListener
{
public:
virtual ~IConsoleListener() {}
virtual void onConsoleCommand(char command) = 0;
};
#endif // __ICONSOLELISTENER_H__

View File

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

View File

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

View File

@@ -27,13 +27,12 @@
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#ifdef WIN32 #ifdef WIN32
# include <winsock2.h> # include <winsock2.h>
# include <malloc.h> # include <windows.h>
# include "3rdparty/winansi.h"
#endif #endif
#include "log/ConsoleLog.h" #include "log/ConsoleLog.h"
#include "log/Log.h" #include "log/Log.h"
@@ -41,6 +40,19 @@
ConsoleLog::ConsoleLog(bool colors) : ConsoleLog::ConsoleLog(bool colors) :
m_colors(colors) m_colors(colors)
{ {
uv_tty_init(uv_default_loop(), &m_tty, 1, 0);
uv_tty_set_mode(&m_tty, UV_TTY_MODE_NORMAL);
# ifdef WIN32
HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
if (handle != INVALID_HANDLE_VALUE) {
DWORD mode = 0;
if (GetConsoleMode(handle, &mode)) {
mode &= ~ENABLE_QUICK_EDIT_MODE;
SetConsoleMode(handle, mode | ENABLE_EXTENDED_FLAGS);
}
}
# endif
} }
@@ -81,7 +93,7 @@ void ConsoleLog::message(int level, const char* fmt, va_list args)
} }
const size_t len = 64 + strlen(fmt) + 2; const size_t len = 64 + strlen(fmt) + 2;
char *buf = static_cast<char *>(alloca(len)); char *buf = new char[len];
sprintf(buf, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n", sprintf(buf, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n",
stime.tm_year + 1900, stime.tm_year + 1900,
@@ -95,18 +107,35 @@ void ConsoleLog::message(int level, const char* fmt, va_list args)
m_colors ? Log::kCL_N : "" m_colors ? Log::kCL_N : ""
); );
vfprintf(stdout, buf, args); print(buf, args);
fflush(stdout);
} }
void ConsoleLog::text(const char* fmt, va_list args) void ConsoleLog::text(const char* fmt, va_list args)
{ {
const int len = 64 + strlen(fmt) + 2; const int len = 64 + strlen(fmt) + 2;
char *buf = static_cast<char *>(alloca(len)); char *buf = new char[len];
sprintf(buf, "%s%s\n", fmt, m_colors ? Log::kCL_N : ""); sprintf(buf, "%s%s\n", fmt, m_colors ? Log::kCL_N : "");
vfprintf(stdout, buf, args); print(buf, args);
fflush(stdout); }
void ConsoleLog::print(char *fmt, va_list args)
{
vsnprintf(m_buf, sizeof(m_buf) - 1, fmt, args);
delete [] fmt;
uv_buf_t buf;
buf.base = strdup(m_buf);
buf.len = strlen(buf.base);
uv_write_t *req = new uv_write_t;
req->data = buf.base;
uv_write(req, reinterpret_cast<uv_stream_t*>(&m_tty), &buf, 1, [](uv_write_t *req, int status) {
free(req->data);
delete req;
});
} }

View File

@@ -25,6 +25,9 @@
#define __CONSOLELOG_H__ #define __CONSOLELOG_H__
#include <uv.h>
#include "interfaces/ILogBackend.h" #include "interfaces/ILogBackend.h"
@@ -33,11 +36,15 @@ class ConsoleLog : public ILogBackend
public: public:
ConsoleLog(bool colors); ConsoleLog(bool colors);
void message(int level, const char* fmt, va_list args) override; void message(int level, const char *fmt, va_list args) override;
void text(const char* fmt, va_list args) override; void text(const char *fmt, va_list args) override;
private: private:
void print(char *fmt, va_list args);
bool m_colors; bool m_colors;
char m_buf[512];
uv_tty_t m_tty;
}; };
#endif /* __CONSOLELOG_H__ */ #endif /* __CONSOLELOG_H__ */

View File

@@ -28,13 +28,6 @@
#include <time.h> #include <time.h>
#ifdef WIN32
# include <winsock2.h>
# include <malloc.h>
# include "3rdparty/winansi.h"
#endif
#include "log/FileLog.h" #include "log/FileLog.h"

View File

@@ -28,12 +28,6 @@
#include <time.h> #include <time.h>
#ifdef WIN32
# include <winsock2.h>
# include <malloc.h>
# include "3rdparty/winansi.h"
#endif
#include "interfaces/ILogBackend.h" #include "interfaces/ILogBackend.h"
#include "log/Log.h" #include "log/Log.h"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -27,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 "2.0.1" #define APP_VERSION "2.2.0"
#define APP_DOMAIN "xmrig.com" #define APP_DOMAIN "xmrig.com"
#define APP_SITE "www.xmrig.com" #define APP_SITE "www.xmrig.com"
#define APP_COPYRIGHT "Copyright (C) 2016-2017 xmrig.com" #define APP_COPYRIGHT "Copyright (C) 2016-2017 xmrig.com"
#define APP_VER_MAJOR 2 #define APP_VER_MAJOR 2
#define APP_VER_MINOR 0 #define APP_VER_MINOR 2
#define APP_VER_BUILD 1 #define APP_VER_BUILD 0
#define APP_VER_REV 0 #define APP_VER_REV 0
#ifdef _MSC_VER #ifdef _MSC_VER

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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