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

Compare commits

...

56 Commits

Author SHA1 Message Date
xmrig
a9178bd468 Update README.md 2018-04-20 11:13:00 +07:00
XMRig
78e2c12202 Fix msvc build. 2018-04-20 10:36:41 +07:00
XMRig
2d2e60a197 Fix x86 build. 2018-04-20 10:14:33 +07:00
xmrig
3f85b11e12 Update CHANGELOG.md 2018-04-19 21:19:00 +07:00
XMRig
91dd5fe68a v2.6.0-beta3 2018-04-19 20:57:23 +07:00
XMRig
fe1649a2c1 Revert old Client::close. 2018-04-19 20:29:23 +07:00
XMRig
9be897eb6b Merge remote-tracking branch 'remotes/origin/feature-advanced-threads' into dev 2018-04-19 19:45:29 +07:00
XMRig
14576f599c Fix ARMv7 build. 2018-04-19 19:44:17 +07:00
XMRig
e119f7f402 Rearrange test vectors, for catch cn-heavy bug. 2018-04-19 13:50:06 +07:00
XMRig
ad94e9a7d2 Simplify ARM implementation. 2018-04-19 11:54:11 +07:00
XMRig
bc67216f7f Added API docs and bug fixes. 2018-04-18 09:58:06 +07:00
XMRig
d04a1fcb8f Add extra information to threads API. 2018-04-17 14:36:32 +07:00
XMRig
c0a72edf9a Added hashrate information to "GET /1/threads" endpoint. 2018-04-17 10:51:29 +07:00
XMRig
c221bf09f6 Use direct access to hashrate in API. 2018-04-17 10:29:37 +07:00
XMRig
b32ec5342e Fixed automatic threads mode for --av above 4 2018-04-17 09:42:53 +07:00
XMRig
9e3f2ae9f9 Added x3 x4 x5 hashing modes. 2018-04-16 15:40:37 +07:00
XMRig
dba1acd302 Finalize config changes. 2018-04-15 21:41:03 +07:00
XMRig
f8bf48a522 Added config only boolean option "hw-aes". 2018-04-15 19:25:09 +07:00
XMRig
f0158ae505 Fix again. 2018-04-15 15:10:41 +07:00
XMRig
6de83dddd6 Fix wrong memory usage displayed for cn-lite. 2018-04-15 15:01:41 +07:00
XMRig
e2d85d78a7 Added information about started threads. 2018-04-15 14:49:39 +07:00
XMRig
6b4f2d0a91 Fixed ARM build. 2018-04-15 12:58:17 +07:00
XMRig
8716f362f8 Fixed HW AES detection. 2018-04-15 11:36:48 +07:00
XMRig
9125b6c251 Rewrite memory allocation. 2018-04-15 11:08:47 +07:00
XMRig
4b71b7aa29 Added class MultiWorker and remove classes SingleWorker and DoubleWorker. 2018-04-14 22:14:57 +07:00
XMRig
c81401ab2d Basic advanced config reader, only single hash supported. 2018-04-14 07:01:12 +07:00
XMRig
c44b299750 Added reader for advanced threads. 2018-04-13 17:59:27 +07:00
XMRig
9ce9147dad Use new method to set affinity. 2018-04-13 09:27:37 +07:00
XMRig
c1800094d0 Move Platform. 2018-04-13 07:23:01 +07:00
XMRig
a6b698d4eb Move common parts of API. 2018-04-13 07:12:53 +07:00
XMRig
51422f4b1e Move xmrig.h to common/xmrig.h. 2018-04-13 07:00:51 +07:00
XMRig
f197f6b1eb Changed directory structure. 2018-04-13 06:38:18 +07:00
XMRig
01c8245846 #548 Fixed macOS build. 2018-04-13 05:05:53 +07:00
XMRig
b13640e4a1 Fixes for build without cn-lite and cn-heavy. 2018-04-12 11:38:43 +07:00
XMRig
a73ad9b089 Fixed build with APP_DEBUG. 2018-04-11 08:29:02 +07:00
XMRig
1ebaf677e0 Move static algo name conversions to Pool class. 2018-04-11 06:39:24 +07:00
XMRig
36ef254c73 Rename class Url to Pool. 2018-04-11 06:09:34 +07:00
XMRig
ad7545d149 Refactoring. 2018-04-11 03:52:23 +07:00
XMRig
3924a16048 Merge branch 'dev' of github.com:xmrig/xmrig into dev 2018-04-10 23:23:11 +07:00
XMRig
0bfd409bdf Remove unused class UploadCtx. 2018-04-10 23:22:49 +07:00
xmrig
916ff33058 Update CHANGELOG.md 2018-04-10 03:56:19 +07:00
xmrig
30903686bd Update README.md 2018-04-10 00:30:06 +07:00
XMRig
82e1138158 v2.6.0-beta2 2018-04-09 23:50:01 +07:00
XMRig
ccbb78d4e9 Improved performance for cryptonight v7. 2018-04-09 21:56:15 +07:00
XMRig
5b664f3681 Fix nonce calculation for --av 4. 2018-04-09 21:21:46 +07:00
XMRig
77207eaaae Fix build with APP_DEBUG. 2018-04-09 20:38:02 +07:00
XMRig
de83cfd53c #519 Fix donation start time randomization. 2018-04-08 22:19:21 +07:00
XMRig
eb56c2b56e Better implementation for algorithm aliases. 2018-04-08 03:20:44 +07:00
XMRig
bb2faaddc0 Added short aliases for algorithm names: cn, cn-lite and cn-heavy. 2018-04-08 02:44:31 +07:00
xmrig
89c095f79e Update CHANGELOG.md 2018-04-07 01:21:56 +07:00
XMRig
dff7636701 Merge branch 'dev' of github.com:xmrig/xmrig into dev 2018-04-07 01:18:22 +07:00
XMRig
3b83fa530c #499 Disabled IPv6 for internal HTTP API by default, was cause issues on some systems. 2018-04-07 01:17:58 +07:00
xmrig
bca087f111 Update CHANGELOG.md 2018-04-07 00:50:24 +07:00
XMRig
ae647699a4 #502 Fixed build without libmicrohttpd. 2018-04-07 00:44:48 +07:00
XMRig
3a67ee6d11 Small fixes. 2018-04-06 23:32:54 +07:00
XMRig
c227e3c7b4 Fix command line option --donate-level. 2018-04-04 00:10:53 +07:00
93 changed files with 2599 additions and 1843 deletions

View File

@@ -1,147 +1,162 @@
# v2.6.0-beta1
- [#476](https://github.com/xmrig/xmrig/issues/476) **Added Cryptonight-Heavy support for Sumokoin ASIC resistance fork.**
- HTTP server now runs in main loop, it make possible easy extend API without worry about thread synchronization.
- Added initial graceful reload support, miner will reload configuration if config file changed, disabled by default until it will be fully implemented and tested.
- Added API endpoint `PUT /1/config` to update current config.
- Added API endpoint `GET /1/config` to get current active config.
- Added API endpoint `GET /1/threads` to get current active threads configuration.
- API endpoint `GET /` now deprecated, use `GET /1/summary` instead.
- Added `--api-no-ipv6` and similar config option to disable IPv6 support for HTTP API.
- Added `--api-no-restricted` to enable full access to api, this option has no effect if `--api-access-token` not specified.
# v2.5.2
- [#448](https://github.com/xmrig/xmrig/issues/478) Fixed broken reconnect.
# v2.5.1
- [#454](https://github.com/xmrig/xmrig/issues/454) Fixed build with libmicrohttpd version below v0.9.35.
- [#456](https://github.com/xmrig/xmrig/issues/459) Verbose errors related to donation pool was not fully silenced.
- [#459](https://github.com/xmrig/xmrig/issues/459) Fixed regression (version 2.5.0 affected) with connection to **xmr.f2pool.com**.
# v2.5.0
- [#434](https://github.com/xmrig/xmrig/issues/434) **Added support for Monero v7 PoW, scheduled on April 6.**
- Added full IPv6 support.
- Added protocol extension, when use the miner with xmrig-proxy 2.5+ no more need manually specify `nicehash` option.
- [#123](https://github.com/xmrig/xmrig-proxy/issues/123) Fixed regression (all versions since 2.4 affected) fragmented responses from pool/proxy was parsed incorrectly.
- [#428](https://github.com/xmrig/xmrig/issues/428) Fixed regression (version 2.4.5 affected) with CPU cache size detection.
# v2.4.5
- [#324](https://github.com/xmrig/xmrig/pull/324) Fixed build without libmicrohttpd (CMake cache issue).
- [#341](https://github.com/xmrig/xmrig/issues/341) Fixed wrong exit code and added command line option `--dry-run`.
- [#385](https://github.com/xmrig/xmrig/pull/385) Up to 20% performance increase for non-AES CPU and fixed Intel Core 2 cache detection.
# v2.4.4
- Added libmicrohttpd version to --version output.
- Fixed bug in singal handler, in some cases miner wasn't shutdown properly.
- Fixed recent MSVC 2017 version detection.
- [#279](https://github.com/xmrig/xmrig/pull/279) Fixed build on some macOS versions.
# v2.4.3
- [#94](https://github.com/xmrig/xmrig/issues/94#issuecomment-342019257) [#216](https://github.com/xmrig/xmrig/issues/216) Added **ARMv8** and **ARMv7** support. Hardware AES supported, thanks [Imran Yusuff](https://github.com/imranyusuff).
- [#157](https://github.com/xmrig/xmrig/issues/157) [#196](https://github.com/xmrig/xmrig/issues/196) Fixed Linux compile issues.
- [#184](https://github.com/xmrig/xmrig/issues/184) Fixed cache size detection for CPUs with disabled Hyper-Threading.
- [#200](https://github.com/xmrig/xmrig/issues/200) In some cases miner was doesn't write log to stdout.
# v2.4.2
- [#60](https://github.com/xmrig/xmrig/issues/60) Added FreeBSD support, thanks [vcambur](https://github.com/vcambur).
- [#153](https://github.com/xmrig/xmrig/issues/153) Fixed issues with dwarfpool.com.
# v2.4.1
- [#147](https://github.com/xmrig/xmrig/issues/147) Fixed comparability with monero-stratum.
# v2.4.0
- Added [HTTP API](https://github.com/xmrig/xmrig/wiki/API).
- Added comments support in config file.
- libjansson replaced to rapidjson.
- [#98](https://github.com/xmrig/xmrig/issues/98) Ignore `keepalive` option with minergate.com and nicehash.com.
- [#101](https://github.com/xmrig/xmrig/issues/101) Fixed MSVC 2017 (15.3) compile time version detection.
- [#108](https://github.com/xmrig/xmrig/issues/108) Silently ignore invalid values for `donate-level` option.
- [#111](https://github.com/xmrig/xmrig/issues/111) Fixed build without AEON support.
# v2.3.1
- [#68](https://github.com/xmrig/xmrig/issues/68) Fixed compatibility with Docker containers, was nothing print on console.
# 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.
# 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
- [#27](https://github.com/xmrig/xmrig/issues/27) Fixed possibility crash on 32bit systems.
# v2.0.0
- Option `--backup-url` removed, instead now possibility specify multiple pools for example: `-o example1.com:3333 -u user1 -p password1 -k -o example2.com:5555 -u user2 -o example3.com:4444 -u user3`
- [#15](https://github.com/xmrig/xmrig/issues/15) Added option `-l, --log-file=FILE` to write log to file.
- [#15](https://github.com/xmrig/xmrig/issues/15) Added option `-S, --syslog` to use syslog for logging, Linux only.
- [#18](https://github.com/xmrig/xmrig/issues/18) Added nice messages for accepted/rejected shares with diff and network latency.
- [#20](https://github.com/xmrig/xmrig/issues/20) Fixed `--cpu-affinity` for more than 32 threads.
- Fixed Windows XP support.
- Fixed regression, option `--no-color` was not fully disable colored output.
- Show resolved pool IP address in miner output.
# v1.0.1
- Fix broken software AES implementation, app has crashed if CPU not support AES-NI, only version 1.0.0 affected.
# v1.0.0
- Miner complete rewritten in C++ with libuv.
- This version should be fully compatible (except config file) with previos versions, many new nice features will come in next versions.
- This is still beta. If you found regression, stability or perfomance issues or have an idea for new feature please fell free to open new [issue](https://github.com/xmrig/xmrig/issues/new).
- Added new option `--print-time=N`, print hashrate report every N seconds.
- New hashrate reports, by default every 60 secons.
- Added Microsoft Visual C++ 2015 and 2017 support.
- Removed dependency on libcurl.
- To compile this version from source please switch to [dev](https://github.com/xmrig/xmrig/tree/dev) branch.
# v0.8.2
- Fixed L2 cache size detection for AMD CPUs (Bulldozer/Piledriver/Steamroller/Excavator architecture).
# v0.8.2
- Fixed L2 cache size detection for AMD CPUs (Bulldozer/Piledriver/Steamroller/Excavator architecture).
- Fixed gcc 7.1 support.
# v0.8.1
- Added nicehash support, detects automaticaly by pool URL, for example `cryptonight.eu.nicehash.com:3355` or manually via option `--nicehash`.
# v0.8.0
- Added double hash mode, also known as lower power mode. `--av=2` and `--av=4`.
- Added smart automatic CPU configuration. Default threads count now depends on size of the L3 cache of CPU.
- Added CryptoNight-Lite support for AEON `-a cryptonight-lite`.
- Added `--max-cpu-usage` option for auto CPU configuration mode.
- Added `--safe` option for adjust threads and algorithm variations to current CPU.
- No more manual steps to enable huge pages on Windows. XMRig will do it automatically.
- Removed BMI2 algorithm variation.
- Removed default pool URL.
# v0.6.0
- Added automatic cryptonight self test.
- New software AES algorithm variation. Will be automatically selected if cpu not support AES-NI.
- Added 32 bit builds.
- Documented [algorithm variations](https://github.com/xmrig/xmrig#algorithm-variations).
# v0.5.0
- Initial public release.
# v2.6.0-beta3
- [#563](https://github.com/xmrig/xmrig/issues/563) **Added [advanced threads mode](https://github.com/xmrig/xmrig/issues/563), now possible configure each thread individually.**
- [#255](https://github.com/xmrig/xmrig/issues/563) Low power mode extended to **triple**, **quard** and **penta** modes.
- [#519](https://github.com/xmrig/xmrig/issues/519) Fixed high donation levels, improved donation start time randomization.
- [#554](https://github.com/xmrig/xmrig/issues/554) Fixed regression with `print-time` option.
# v2.6.0-beta2
- Improved performance for `cryptonight v7` especially in double hash mode.
- [#499](https://github.com/xmrig/xmrig/issues/499) IPv6 disabled for internal HTTP API by default, was causing issues on some systems.
- Added short aliases for algorithm names: `cn`, `cn-lite` and `cn-heavy`.
- Fixed regressions (v2.6.0-beta1 affected)
- [#494](https://github.com/xmrig/xmrig/issues/494) Command line option `--donate-level` was broken.
- [#502](https://github.com/xmrig/xmrig/issues/502) Build without libmicrohttpd was broken.
- Fixed nonce calculation for `--av 4` (software AES, double hash) was causing reduction of effective hashrate and rejected shares on nicehash.
# v2.6.0-beta1
- [#476](https://github.com/xmrig/xmrig/issues/476) **Added Cryptonight-Heavy support for Sumokoin ASIC resistance fork.**
- HTTP server now runs in main loop, it make possible easy extend API without worry about thread synchronization.
- Added initial graceful reload support, miner will reload configuration if config file changed, disabled by default until it will be fully implemented and tested.
- Added API endpoint `PUT /1/config` to update current config.
- Added API endpoint `GET /1/config` to get current active config.
- Added API endpoint `GET /1/threads` to get current active threads configuration.
- API endpoint `GET /` now deprecated, use `GET /1/summary` instead.
- Added `--api-no-ipv6` and similar config option to disable IPv6 support for HTTP API.
- Added `--api-no-restricted` to enable full access to api, this option has no effect if `--api-access-token` not specified.
# v2.5.2
- [#448](https://github.com/xmrig/xmrig/issues/478) Fixed broken reconnect.
# v2.5.1
- [#454](https://github.com/xmrig/xmrig/issues/454) Fixed build with libmicrohttpd version below v0.9.35.
- [#456](https://github.com/xmrig/xmrig/issues/459) Verbose errors related to donation pool was not fully silenced.
- [#459](https://github.com/xmrig/xmrig/issues/459) Fixed regression (version 2.5.0 affected) with connection to **xmr.f2pool.com**.
# v2.5.0
- [#434](https://github.com/xmrig/xmrig/issues/434) **Added support for Monero v7 PoW, scheduled on April 6.**
- Added full IPv6 support.
- Added protocol extension, when use the miner with xmrig-proxy 2.5+ no more need manually specify `nicehash` option.
- [#123](https://github.com/xmrig/xmrig-proxy/issues/123) Fixed regression (all versions since 2.4 affected) fragmented responses from pool/proxy was parsed incorrectly.
- [#428](https://github.com/xmrig/xmrig/issues/428) Fixed regression (version 2.4.5 affected) with CPU cache size detection.
# v2.4.5
- [#324](https://github.com/xmrig/xmrig/pull/324) Fixed build without libmicrohttpd (CMake cache issue).
- [#341](https://github.com/xmrig/xmrig/issues/341) Fixed wrong exit code and added command line option `--dry-run`.
- [#385](https://github.com/xmrig/xmrig/pull/385) Up to 20% performance increase for non-AES CPU and fixed Intel Core 2 cache detection.
# v2.4.4
- Added libmicrohttpd version to --version output.
- Fixed bug in singal handler, in some cases miner wasn't shutdown properly.
- Fixed recent MSVC 2017 version detection.
- [#279](https://github.com/xmrig/xmrig/pull/279) Fixed build on some macOS versions.
# v2.4.3
- [#94](https://github.com/xmrig/xmrig/issues/94#issuecomment-342019257) [#216](https://github.com/xmrig/xmrig/issues/216) Added **ARMv8** and **ARMv7** support. Hardware AES supported, thanks [Imran Yusuff](https://github.com/imranyusuff).
- [#157](https://github.com/xmrig/xmrig/issues/157) [#196](https://github.com/xmrig/xmrig/issues/196) Fixed Linux compile issues.
- [#184](https://github.com/xmrig/xmrig/issues/184) Fixed cache size detection for CPUs with disabled Hyper-Threading.
- [#200](https://github.com/xmrig/xmrig/issues/200) In some cases miner was doesn't write log to stdout.
# v2.4.2
- [#60](https://github.com/xmrig/xmrig/issues/60) Added FreeBSD support, thanks [vcambur](https://github.com/vcambur).
- [#153](https://github.com/xmrig/xmrig/issues/153) Fixed issues with dwarfpool.com.
# v2.4.1
- [#147](https://github.com/xmrig/xmrig/issues/147) Fixed comparability with monero-stratum.
# v2.4.0
- Added [HTTP API](https://github.com/xmrig/xmrig/wiki/API).
- Added comments support in config file.
- libjansson replaced to rapidjson.
- [#98](https://github.com/xmrig/xmrig/issues/98) Ignore `keepalive` option with minergate.com and nicehash.com.
- [#101](https://github.com/xmrig/xmrig/issues/101) Fixed MSVC 2017 (15.3) compile time version detection.
- [#108](https://github.com/xmrig/xmrig/issues/108) Silently ignore invalid values for `donate-level` option.
- [#111](https://github.com/xmrig/xmrig/issues/111) Fixed build without AEON support.
# v2.3.1
- [#68](https://github.com/xmrig/xmrig/issues/68) Fixed compatibility with Docker containers, was nothing print on console.
# 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.
# 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
- [#27](https://github.com/xmrig/xmrig/issues/27) Fixed possibility crash on 32bit systems.
# v2.0.0
- Option `--backup-url` removed, instead now possibility specify multiple pools for example: `-o example1.com:3333 -u user1 -p password1 -k -o example2.com:5555 -u user2 -o example3.com:4444 -u user3`
- [#15](https://github.com/xmrig/xmrig/issues/15) Added option `-l, --log-file=FILE` to write log to file.
- [#15](https://github.com/xmrig/xmrig/issues/15) Added option `-S, --syslog` to use syslog for logging, Linux only.
- [#18](https://github.com/xmrig/xmrig/issues/18) Added nice messages for accepted/rejected shares with diff and network latency.
- [#20](https://github.com/xmrig/xmrig/issues/20) Fixed `--cpu-affinity` for more than 32 threads.
- Fixed Windows XP support.
- Fixed regression, option `--no-color` was not fully disable colored output.
- Show resolved pool IP address in miner output.
# v1.0.1
- Fix broken software AES implementation, app has crashed if CPU not support AES-NI, only version 1.0.0 affected.
# v1.0.0
- Miner complete rewritten in C++ with libuv.
- This version should be fully compatible (except config file) with previos versions, many new nice features will come in next versions.
- This is still beta. If you found regression, stability or perfomance issues or have an idea for new feature please fell free to open new [issue](https://github.com/xmrig/xmrig/issues/new).
- Added new option `--print-time=N`, print hashrate report every N seconds.
- New hashrate reports, by default every 60 secons.
- Added Microsoft Visual C++ 2015 and 2017 support.
- Removed dependency on libcurl.
- To compile this version from source please switch to [dev](https://github.com/xmrig/xmrig/tree/dev) branch.
# v0.8.2
- Fixed L2 cache size detection for AMD CPUs (Bulldozer/Piledriver/Steamroller/Excavator architecture).
# v0.8.2
- Fixed L2 cache size detection for AMD CPUs (Bulldozer/Piledriver/Steamroller/Excavator architecture).
- Fixed gcc 7.1 support.
# v0.8.1
- Added nicehash support, detects automaticaly by pool URL, for example `cryptonight.eu.nicehash.com:3355` or manually via option `--nicehash`.
# v0.8.0
- Added double hash mode, also known as lower power mode. `--av=2` and `--av=4`.
- Added smart automatic CPU configuration. Default threads count now depends on size of the L3 cache of CPU.
- Added CryptoNight-Lite support for AEON `-a cryptonight-lite`.
- Added `--max-cpu-usage` option for auto CPU configuration mode.
- Added `--safe` option for adjust threads and algorithm variations to current CPU.
- No more manual steps to enable huge pages on Windows. XMRig will do it automatically.
- Removed BMI2 algorithm variation.
- Removed default pool URL.
# v0.6.0
- Added automatic cryptonight self test.
- New software AES algorithm variation. Will be automatically selected if cpu not support AES-NI.
- Added 32 bit builds.
- Documented [algorithm variations](https://github.com/xmrig/xmrig#algorithm-variations).
# v0.5.0
- Initial public release.

View File

@@ -12,16 +12,18 @@ include (cmake/cpu.cmake)
set(HEADERS
src/api/Api.h
src/api/NetworkState.h
src/App.h
src/common/config/CommonConfig.h
src/common/config/ConfigLoader.h
src/common/config/ConfigWatcher.h
src/common/Platform.h
src/common/utils/c_str.h
src/common/utils/mm_malloc.h
src/common/xmrig.h
src/Console.h
src/core/CommonConfig.h
src/core/Config.cpp
src/core/ConfigLoader.cpp
src/core/ConfigLoader.h
src/core/ConfigLoader_platform.h
src/core/ConfigWatcher.cpp
src/core/Controller.h
src/Cpu.h
src/interfaces/IClientListener.h
@@ -45,23 +47,20 @@ set(HEADERS
src/net/Job.h
src/net/JobResult.h
src/net/Network.h
src/net/Pool.h
src/net/Storage.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/Platform.h
src/Summary.h
src/version.h
src/workers/CpuThread.h
src/workers/DoubleWorker.h
src/workers/Handle.h
src/workers/Hashrate.h
src/workers/SingleWorker.h
src/workers/MultiWorker.h
src/workers/Worker.h
src/workers/Workers.h
src/xmrig.h
)
set(HEADERS_CRYPTO
@@ -87,14 +86,14 @@ else()
endif()
set(SOURCES
src/api/Api.cpp
src/api/NetworkState.cpp
src/App.cpp
src/common/config/CommonConfig.cpp
src/common/config/ConfigLoader.cpp
src/common/config/ConfigWatcher.cpp
src/common/Platform.cpp
src/Console.cpp
src/core/CommonConfig.cpp
src/core/Config.cpp
src/core/ConfigLoader.cpp
src/core/ConfigWatcher.cpp
src/core/Controller.cpp
src/log/ConsoleLog.cpp
src/log/FileLog.cpp
@@ -103,18 +102,16 @@ set(SOURCES
src/net/Client.cpp
src/net/Job.cpp
src/net/Network.cpp
src/net/Pool.cpp
src/net/strategies/DonateStrategy.cpp
src/net/strategies/FailoverStrategy.cpp
src/net/strategies/SinglePoolStrategy.cpp
src/net/SubmitResult.cpp
src/net/Url.cpp
src/Platform.cpp
src/Summary.cpp
src/workers/CpuThread.cpp
src/workers/DoubleWorker.cpp
src/workers/Handle.cpp
src/workers/Hashrate.cpp
src/workers/SingleWorker.cpp
src/workers/MultiWorker.cpp
src/workers/Worker.cpp
src/workers/Workers.cpp
src/xmrig.cpp
@@ -132,9 +129,9 @@ if (WIN32)
set(SOURCES_OS
res/app.rc
src/App_win.cpp
src/common/Platform_win.cpp
src/Cpu_win.cpp
src/Mem_win.cpp
src/Platform_win.cpp
)
add_definitions(/DWIN32)
@@ -142,16 +139,16 @@ if (WIN32)
elseif (APPLE)
set(SOURCES_OS
src/App_unix.cpp
src/common/Platform_mac.cpp
src/Cpu_mac.cpp
src/Mem_unix.cpp
src/Platform_mac.cpp
)
else()
set(SOURCES_OS
src/App_unix.cpp
src/common/Platform_unix.cpp
src/Cpu_unix.cpp
src/Mem_unix.cpp
src/Platform_unix.cpp
)
set(EXTRA_LIBS pthread rt)
@@ -214,14 +211,16 @@ if (WITH_HTTPD)
if (MHD_FOUND)
include_directories(${MHD_INCLUDE_DIRS})
set(HTTPD_SOURCES
src/api/Api.h
src/api/ApiRouter.h
src/api/HttpBody.h
src/api/Httpd.h
src/api/HttpReply.h
src/api/HttpRequest.h
src/common/api/HttpBody.h
src/common/api/Httpd.h
src/common/api/HttpReply.h
src/common/api/HttpRequest.h
src/api/Api.cpp
src/api/ApiRouter.cpp
src/api/Httpd.cpp
src/api/HttpRequest.cpp
src/common/api/Httpd.cpp
src/common/api/HttpRequest.cpp
)
else()
message(FATAL_ERROR "microhttpd NOT found: use `-DWITH_HTTPD=OFF` to build without http deamon support")

View File

@@ -124,10 +124,10 @@ Please note performance is highly dependent on system load. The numbers above ar
## Release checksums
### SHA-256
```
bd14bc3cfd9528e4a7583ab39aecc876250333e1e0faab83781584bb7f65e3eb xmrig-2.6.0-beta1-xenial-amd64.tar.gz/xmrig-2.6.0-beta1/xmrig
32eebf71e5631029202ae5cbf6f03caad912f1722aa86a1be01a26d491801aba xmrig-2.6.0-beta1-gcc-win32.zip/xmrig.exe
1cc08844ff019408e2e2c9560fee0c4e0b2dbc2a72bcc1c1da4a847a1787eca3 xmrig-2.6.0-beta1-gcc-win64.zip/xmrig.exe
fdf99aa8e7792a34b1be0cc6c77e4e83ff9a4b21abb27989f7927dcfed82f6e2 xmrig-2.6.0-beta1-msvc-win64.zip/xmrig.exe
6b32fefb356b27caa2180be17755d09639f0654096a1a0c61e8f10f4f2ac1626 xmrig-2.6.0-beta3-xenial-amd64.tar.gz/xmrig-2.6.0-beta3/xmrig
c8b40f4d7aac9d0cc7c3d02cadeac91b0bdb034aae2fb6b415d503272eabb987 xmrig-2.6.0-beta3-gcc-win32.zip/xmrig.exe
32cf7958f97a23296186e38a4addb9cf234adcbd9c7914b15e4209a87fe272e7 xmrig-2.6.0-beta3-gcc-win64.zip/xmrig.exe
4f176ee4c4be52701edc0d573cf9647c4aacbb4ff14975b80b98e6fe63068542 xmrig-2.6.0-beta3-msvc-win64.zip/xmrig.exe
```
## Contacts

View File

@@ -13,10 +13,10 @@ endif()
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-strict-aliasing")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fno-exceptions -fno-rtti")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s -funroll-loops -fvariable-expansion-in-unroller -ftree-loop-if-convert-stores -fmerge-all-constants -fbranch-target-load-optimize2")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -s")
if (XMRIG_ARMv8)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a+crypto")

53
doc/API.md Normal file
View File

@@ -0,0 +1,53 @@
# HTTP API
If you want use API you need choice a port where is internal HTTP server will listen for incoming connections. API will not available if miner built without `libmicrohttpd`.
Example configuration:
```json
"api": {
"port": 44444,
"access-token": "TOKEN",
"worker-id": null,
"ipv6": false,
"restricted": false
},
```
* **port** Port for incoming connections `http://<miner ip>:<port>`.
* **access-token** [Bearer](https://gist.github.com/xmrig/c75fdd1f8e0f3bac05500be2ab718f8e#file-api-html-L54) access token to secure access to API.
* **worker-id** Optional worker name, if not set will be detected automatically.
* **ipv6** Enable (`true`) or disable (`false`) IPv6 for API.
* **restricted** Use `false` to allow remote configuration.
If you prefer use command line options instead of config file, you can use options: `--api-port`, `--api-access-token`, `--api-worker-id`, `--api-ipv6` and `api-no-restricted`.
## Endpoints
### GET /1/summary
Get miner summary information. [Example](api/1/summary.json).
### GET /1/threads
Get detailed information about miner threads. [Example](api/1/threads.json).
## Restricted endpoints
All API endpoints below allow access to sensitive information and remote configure miner. You should set `access-token` and allow unrestricted access (`"restricted": false`).
### GET /1/config
Get current miner configuration. [Example](api/1/config.json).
### PUT /1/config
Update current miner configuration. Common use case, get current configuration, make changes, and upload it to miner.
Curl example:
```
curl -v --data-binary @config.json -X PUT -H "Content-Type: application/json" -H "Authorization: Bearer SECRET" http://127.0.0.1:44444/1/config
```

63
doc/api/1/config.json Normal file
View File

@@ -0,0 +1,63 @@
{
"algo": "cryptonight",
"api": {
"port": 44444,
"access-token": "TOKEN",
"worker-id": null,
"ipv6": false,
"restricted": false
},
"av": 1,
"background": false,
"colors": true,
"cpu-affinity": null,
"cpu-priority": null,
"donate-level": 5,
"huge-pages": true,
"hw-aes": null,
"log-file": null,
"max-cpu-usage": 75,
"pools": [
{
"url": "pool.monero.hashvault.pro:3333",
"user": "48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD",
"pass": "x",
"keepalive": false,
"nicehash": false,
"variant": -1
},
{
"url": "pool.supportxmr.com:3333",
"user": "48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD",
"pass": "x",
"keepalive": false,
"nicehash": false,
"variant": -1
}
],
"print-time": 60,
"retries": 5,
"retry-pause": 5,
"safe": false,
"threads": [
{
"low_power_mode": 1,
"affine_to_cpu": 0
},
{
"low_power_mode": 1,
"affine_to_cpu": 1
},
{
"low_power_mode": 1,
"affine_to_cpu": 2
},
{
"low_power_mode": 1,
"affine_to_cpu": 3
}
],
"user-agent": null,
"syslog": false,
"watch": false
}

73
doc/api/1/summary.json Normal file
View File

@@ -0,0 +1,73 @@
{
"id": "92f3104f9a2ee78c",
"worker_id": "Ubuntu-1604-xenial-64-minimal",
"version": "2.6.0-beta3",
"kind": "cpu",
"ua": "XMRig/2.6.0-beta3 (Linux x86_64) libuv/1.8.0 gcc/5.4.0",
"cpu": {
"brand": "Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz",
"aes": true,
"x64": true,
"sockets": 1
},
"algo": "cryptonight",
"hugepages": true,
"donate_level": 5,
"hashrate": {
"total": [
296.24,
296.23,
295.97
],
"highest": 296.5,
"threads": [
[
73.39,
73.39,
73.28
],
[
74.72,
74.72,
74.71
],
[
74.72,
74.72,
74.71
],
[
73.39,
73.39,
73.27
]
]
},
"results": {
"diff_current": 9990,
"shares_good": 30,
"shares_total": 30,
"avg_time": 31,
"hashes_total": 311833,
"best": [
278199,
181923,
103717,
96632,
56154,
51580,
45667,
33159,
29581,
29514
],
"error_log": []
},
"connection": {
"pool": "pool.monero.hashvault.pro:3333",
"uptime": 953,
"ping": 35,
"failures": 0,
"error_log": []
}
}

65
doc/api/1/threads.json Normal file
View File

@@ -0,0 +1,65 @@
{
"hugepages": [
4,
4
],
"memory": 8388608,
"threads": [
{
"type": "cpu",
"algo": "cryptonight",
"av": 1,
"low_power_mode": 1,
"affine_to_cpu": 0,
"priority": -1,
"soft_aes": false,
"hashrate": [
73.39,
73.4,
73.28
]
},
{
"type": "cpu",
"algo": "cryptonight",
"av": 1,
"low_power_mode": 1,
"affine_to_cpu": 1,
"priority": -1,
"soft_aes": false,
"hashrate": [
74.72,
74.72,
74.7
]
},
{
"type": "cpu",
"algo": "cryptonight",
"av": 1,
"low_power_mode": 1,
"affine_to_cpu": 2,
"priority": -1,
"soft_aes": false,
"hashrate": [
74.71,
74.72,
74.7
]
},
{
"type": "cpu",
"algo": "cryptonight",
"av": 1,
"low_power_mode": 1,
"affine_to_cpu": 3,
"priority": -1,
"soft_aes": false,
"hashrate": [
73.39,
73.4,
73.28
]
}
]
}

View File

@@ -28,6 +28,7 @@
#include "api/Api.h"
#include "App.h"
#include "common/Platform.h"
#include "Console.h"
#include "core/Config.h"
#include "core/Controller.h"
@@ -38,14 +39,13 @@
#include "log/Log.h"
#include "Mem.h"
#include "net/Network.h"
#include "Platform.h"
#include "Summary.h"
#include "version.h"
#include "workers/Workers.h"
#ifndef XMRIG_NO_HTTPD
# include "api/Httpd.h"
# include "common/api/Httpd.h"
#endif
@@ -76,8 +76,6 @@ App::App(int argc, char **argv) :
App::~App()
{
Mem::release();
uv_tty_reset_mode();
delete m_console;
@@ -101,11 +99,7 @@ int App::exec()
background();
Mem::allocate(m_controller->config()->algorithm(),
m_controller->config()->threadsCount(),
m_controller->config()->isDoubleHash(),
m_controller->config()->isHugePages()
);
Mem::init(m_controller->config()->isHugePages());
Summary::print(m_controller);

View File

@@ -31,7 +31,6 @@
#include "App.h"
#include "core/Config.h"
#include "core/Controller.h"
#include "Cpu.h"
#include "log/Log.h"
@@ -39,11 +38,6 @@ void App::background()
{
signal(SIGPIPE, SIG_IGN);
const int64_t affinity = m_controller->config()->affinity();
if (affinity != -1L) {
Cpu::setAffinity(-1, affinity);
}
if (!m_controller->config()->isBackground()) {
return;
}

View File

@@ -27,18 +27,12 @@
#include "App.h"
#include "Cpu.h"
#include "core/Controller.h"
#include "core/Config.h"
void App::background()
{
const int64_t affinity = m_controller->config()->affinity();
if (affinity != -1L) {
Cpu::setAffinity(-1, affinity);
}
if (!m_controller->config()->isBackground()) {
return;
}

View File

@@ -26,26 +26,27 @@
#include <math.h>
#include <string.h>
#include "Cpu.h"
bool Cpu::m_l2_exclusive = false;
char Cpu::m_brand[64] = { 0 };
int Cpu::m_flags = 0;
int Cpu::m_l2_cache = 0;
int Cpu::m_l3_cache = 0;
int Cpu::m_sockets = 1;
int Cpu::m_totalCores = 0;
int Cpu::m_totalThreads = 0;
bool Cpu::m_l2_exclusive = false;
char Cpu::m_brand[64] = { 0 };
int Cpu::m_flags = 0;
int Cpu::m_l2_cache = 0;
int Cpu::m_l3_cache = 0;
int Cpu::m_sockets = 1;
int Cpu::m_totalCores = 0;
size_t Cpu::m_totalThreads = 0;
int Cpu::optimalThreadsCount(xmrig::Algo algo, bool doubleHash, int maxCpuUsage)
size_t Cpu::optimalThreadsCount(size_t size, int maxCpuUsage)
{
if (m_totalThreads == 1) {
return 1;
}
int cache = 0;
size_t cache = 0;
if (m_l3_cache) {
cache = m_l2_exclusive ? (m_l2_cache + m_l3_cache) : m_l3_cache;
}
@@ -53,22 +54,14 @@ int Cpu::optimalThreadsCount(xmrig::Algo algo, bool doubleHash, int maxCpuUsage)
cache = m_l2_cache;
}
int count = 0;
int size = 2048;
if (algo == xmrig::CRYPTONIGHT_LITE) {
size = 1024;
}
else if (algo == xmrig::CRYPTONIGHT_HEAVY) {
size = 4096;
}
if (doubleHash) {
size *= 2;
}
size_t count = 0;
if (cache) {
count = cache / size;
if (cache % size >= size / 2) {
count++;
}
}
else {
count = m_totalThreads / 2;

View File

@@ -28,9 +28,6 @@
#include <stdint.h>
#include "xmrig.h"
class Cpu
{
public:
@@ -40,9 +37,8 @@ public:
BMI2 = 4
};
static int optimalThreadsCount(xmrig::Algo algo, bool doubleHash, int maxCpuUsage);
static size_t optimalThreadsCount(size_t size, int maxCpuUsage);
static void init();
static void setAffinity(int id, uint64_t mask);
static inline bool hasAES() { return (m_flags & AES) != 0; }
static inline bool isX64() { return (m_flags & X86_64) != 0; }
@@ -63,7 +59,7 @@ private:
static int m_l3_cache;
static int m_sockets;
static int m_totalCores;
static int m_totalThreads;
static size_t m_totalThreads;
};

View File

@@ -4,8 +4,8 @@
* 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>
*
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 XMRig <https://github.com/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
@@ -28,16 +28,16 @@
#include "Cpu.h"
char Cpu::m_brand[64] = { 0 };
int Cpu::m_flags = 0;
int Cpu::m_l2_cache = 0;
int Cpu::m_l3_cache = 0;
int Cpu::m_sockets = 1;
int Cpu::m_totalCores = 0;
int Cpu::m_totalThreads = 0;
char Cpu::m_brand[64] = { 0 };
int Cpu::m_flags = 0;
int Cpu::m_l2_cache = 0;
int Cpu::m_l3_cache = 0;
int Cpu::m_sockets = 1;
int Cpu::m_totalCores = 0;
size_t Cpu::m_totalThreads = 0;
int Cpu::optimalThreadsCount(xmrig::Algo algo, bool doubleHash, int maxCpuUsage)
size_t Cpu::optimalThreadsCount(size_t size, int maxCpuUsage)
{
return m_totalThreads;
}

View File

@@ -4,8 +4,8 @@
* 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>
*
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2018 XMRig <https://github.com/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
@@ -38,8 +38,3 @@ void Cpu::init()
initCommon();
}
void Cpu::setAffinity(int id, uint64_t mask)
{
}

View File

@@ -52,28 +52,3 @@ void Cpu::init()
initCommon();
}
void Cpu::setAffinity(int id, uint64_t mask)
{
cpu_set_t set;
CPU_ZERO(&set);
for (int i = 0; i < m_totalThreads; i++) {
if (mask & (1UL << i)) {
CPU_SET(i, &set);
}
}
if (id == -1) {
# ifndef __FreeBSD__
sched_setaffinity(0, sizeof(&set), &set);
# endif
} else {
# ifndef __ANDROID__
pthread_setaffinity_np(pthread_self(), sizeof(&set), &set);
# else
sched_setaffinity(gettid(), sizeof(&set), &set);
# endif
}
}

View File

@@ -39,14 +39,3 @@ void Cpu::init()
initCommon();
}
void Cpu::setAffinity(int id, uint64_t mask)
{
if (id == -1) {
SetProcessAffinityMask(GetCurrentProcess(), mask);
}
else {
SetThreadAffinityMask(GetCurrentThread(), mask);
}
}

View File

@@ -23,70 +23,49 @@
*/
#include <memory.h>
#include "common/utils/mm_malloc.h"
#include "crypto/CryptoNight.h"
#include "crypto/CryptoNight_constants.h"
#include "Mem.h"
bool Mem::m_doubleHash = false;
int Mem::m_algo = 0;
int Mem::m_flags = 0;
int Mem::m_threads = 0;
size_t Mem::m_offset = 0;
size_t Mem::m_size = 0;
alignas(16) uint8_t *Mem::m_memory = nullptr;
bool Mem::m_enabled = true;
int Mem::m_flags = 0;
cryptonight_ctx *Mem::create(int threadId)
MemInfo Mem::create(cryptonight_ctx **ctx, xmrig::Algo algorithm, size_t count)
{
using namespace xmrig;
MemInfo info;
info.size = cn_select_memory(algorithm) * count;
# ifndef XMRIG_NO_AEON
if (m_algo == xmrig::CRYPTONIGHT_LITE) {
return createLite(threadId);
}
info.size += info.size % cn_select_memory<CRYPTONIGHT>();
# endif
const size_t size = m_algo == xmrig::CRYPTONIGHT_HEAVY ? xmrig::cn_select_memory<xmrig::CRYPTONIGHT_HEAVY>()
: xmrig::cn_select_memory<xmrig::CRYPTONIGHT>();
info.pages = info.size / cn_select_memory<CRYPTONIGHT>();
cryptonight_ctx *ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[size - sizeof(cryptonight_ctx) * (threadId + 1)]);
allocate(info, m_enabled);
const int ratio = m_doubleHash ? 2 : 1;
ctx->memory = &m_memory[size * (threadId * ratio + 1)];
for (size_t i = 0; i < count; ++i) {
cryptonight_ctx *c = static_cast<cryptonight_ctx *>(_mm_malloc(sizeof(cryptonight_ctx), 4096));
c->memory = info.memory + (i * cn_select_memory(algorithm));
return ctx;
}
void *Mem::calloc(size_t num, size_t size)
{
void *mem = &m_memory[m_offset];
m_offset += (num * size);
memset(mem, 0, num * size);
return mem;
}
#ifndef XMRIG_NO_AEON
cryptonight_ctx *Mem::createLite(int threadId) {
cryptonight_ctx *ctx;
if (!m_doubleHash) {
const size_t offset = MONERO_MEMORY * (threadId + 1);
ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[offset + AEON_MEMORY]);
ctx->memory = &m_memory[offset];
return ctx;
ctx[i] = c;
}
ctx = reinterpret_cast<cryptonight_ctx *>(&m_memory[MONERO_MEMORY - sizeof(cryptonight_ctx) * (threadId + 1)]);
ctx->memory = &m_memory[MONERO_MEMORY * (threadId + 1)];
return ctx;
return info;
}
#endif
void Mem::release(cryptonight_ctx **ctx, size_t count, MemInfo &info)
{
release(info);
for (size_t i = 0; i < count; ++i) {
_mm_free(ctx[i]);
}
}

View File

@@ -30,12 +30,22 @@
#include <stdint.h>
#include "xmrig.h"
#include "common/xmrig.h"
struct cryptonight_ctx;
struct MemInfo
{
alignas(16) uint8_t *memory;
size_t hugePages;
size_t pages;
size_t size;
};
class Mem
{
public:
@@ -45,29 +55,18 @@ public:
Lock = 4
};
static bool allocate(xmrig::Algo 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 MemInfo create(cryptonight_ctx **ctx, xmrig::Algo algorithm, size_t count);
static void init(bool enabled);
static void release(cryptonight_ctx **ctx, size_t count, MemInfo &info);
static inline bool isDoubleHash() { return m_doubleHash; }
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; }
private:
static bool m_doubleHash;
static int m_algo;
static int m_flags;
static int m_threads;
static size_t m_offset;
static size_t m_size;
alignas(16) static uint8_t *m_memory;
static void allocate(MemInfo &info, bool enabled);
static void release(MemInfo &info);
# ifndef XMRIG_NO_AEON
static cryptonight_ctx *createLite(int threadId);
# endif
static int m_flags;
static bool m_enabled;
};

View File

@@ -27,75 +27,63 @@
#include <sys/mman.h>
#if defined(XMRIG_ARM) && !defined(__clang__)
# include "aligned_malloc.h"
#else
# include <mm_malloc.h>
#endif
#include "common/utils/mm_malloc.h"
#include "common/xmrig.h"
#include "crypto/CryptoNight.h"
#include "log/Log.h"
#include "Mem.h"
#include "xmrig.h"
bool Mem::allocate(xmrig::Algo algo, int threads, bool doubleHash, bool enabled)
void Mem::init(bool enabled)
{
m_algo = algo;
m_threads = threads;
m_doubleHash = doubleHash;
m_enabled = enabled;
}
const int ratio = (doubleHash && algo != xmrig::CRYPTONIGHT_LITE) ? 2 : 1;
m_size = MONERO_MEMORY * (threads * ratio + 1);
if (algo == xmrig::CRYPTONIGHT_HEAVY) {
m_size *= 2;
}
void Mem::allocate(MemInfo &info, bool enabled)
{
info.hugePages = 0;
if (!enabled) {
m_memory = static_cast<uint8_t*>(_mm_malloc(m_size, 16));
return true;
}
info.memory = static_cast<uint8_t*>(_mm_malloc(info.size, 4096));
m_flags |= HugepagesAvailable;
return;
}
# if defined(__APPLE__)
m_memory = static_cast<uint8_t*>(mmap(0, m_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0));
info.memory = static_cast<uint8_t*>(mmap(0, info.size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0));
# elif defined(__FreeBSD__)
m_memory = static_cast<uint8_t*>(mmap(0, m_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER | MAP_PREFAULT_READ, -1, 0));
info.memory = static_cast<uint8_t*>(mmap(0, info.size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER | MAP_PREFAULT_READ, -1, 0));
# else
m_memory = static_cast<uint8_t*>(mmap(0, m_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0));
info.memory = static_cast<uint8_t*>(mmap(0, info.size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0));
# endif
if (m_memory == MAP_FAILED) {
m_memory = static_cast<uint8_t*>(_mm_malloc(m_size, 16));
return true;
if (info.memory == MAP_FAILED) {
return allocate(info, false);;
}
m_flags |= HugepagesEnabled;
info.hugePages = info.pages;
if (madvise(m_memory, m_size, MADV_RANDOM | MADV_WILLNEED) != 0) {
if (madvise(info.memory, info.size, MADV_RANDOM | MADV_WILLNEED) != 0) {
LOG_ERR("madvise failed");
}
if (mlock(m_memory, m_size) == 0) {
if (mlock(info.memory, info.size) == 0) {
m_flags |= Lock;
}
return true;
}
void Mem::release()
void Mem::release(MemInfo &info)
{
if (m_flags & HugepagesEnabled) {
if (info.hugePages) {
if (m_flags & Lock) {
munlock(m_memory, m_size);
munlock(info.memory, info.size);
}
munmap(m_memory, m_size);
munmap(info.memory, info.size);
}
else {
_mm_free(m_memory);
_mm_free(info.memory);
}
}

View File

@@ -28,16 +28,13 @@
#include <ntsecapi.h>
#include <tchar.h>
#ifdef __GNUC__
# include <mm_malloc.h>
#else
# include <malloc.h>
#endif
#include "log/Log.h"
#include "common/utils/mm_malloc.h"
#include "common/xmrig.h"
#include "crypto/CryptoNight.h"
#include "crypto/CryptoNight_constants.h"
#include "log/Log.h"
#include "Mem.h"
#include "xmrig.h"
/*****************************************************************
@@ -145,46 +142,43 @@ static BOOL TrySetLockPagesPrivilege() {
}
bool Mem::allocate(xmrig::Algo algo, int threads, bool doubleHash, bool enabled)
void Mem::init(bool enabled)
{
m_algo = algo;
m_threads = threads;
m_doubleHash = doubleHash;
m_enabled = enabled;
const int ratio = (doubleHash && algo != xmrig::CRYPTONIGHT_LITE) ? 2 : 1;
m_size = MONERO_MEMORY * (threads * ratio + 1);
if (algo == xmrig::CRYPTONIGHT_HEAVY) {
m_size *= 2;
}
if (!enabled) {
m_memory = static_cast<uint8_t*>(_mm_malloc(m_size, 16));
return true;
}
if (TrySetLockPagesPrivilege()) {
if (enabled && TrySetLockPagesPrivilege()) {
m_flags |= HugepagesAvailable;
}
m_memory = static_cast<uint8_t*>(VirtualAlloc(NULL, m_size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE));
if (!m_memory) {
m_memory = static_cast<uint8_t*>(_mm_malloc(m_size, 16));
}
else {
m_flags |= HugepagesEnabled;
}
return true;
}
void Mem::release()
void Mem::allocate(MemInfo &info, bool enabled)
{
if (m_flags & HugepagesEnabled) {
VirtualFree(m_memory, 0, MEM_RELEASE);
info.hugePages = 0;
if (!enabled) {
info.memory = static_cast<uint8_t*>(_mm_malloc(info.size, 4096));
return;
}
info.memory = static_cast<uint8_t*>(VirtualAlloc(nullptr, info.size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE));
if (info.memory) {
info.hugePages = info.pages;
return;
}
allocate(info, false);
}
void Mem::release(MemInfo &info)
{
if (info.hugePages) {
VirtualFree(info.memory, 0, MEM_RELEASE);
}
else {
_mm_free(m_memory);
_mm_free(info.memory);
}
}

View File

@@ -32,7 +32,7 @@
#include "Cpu.h"
#include "log/Log.h"
#include "Mem.h"
#include "net/Url.h"
#include "net/Pool.h"
#include "Summary.h"
#include "version.h"
@@ -58,14 +58,15 @@ static void print_versions(xmrig::Config *config)
static void print_memory(xmrig::Config *config) {
# ifdef _WIN32
if (config->isColors()) {
Log::i()->text("\x1B[01;32m * \x1B[01;37mHUGE PAGES: %s, %s",
Mem::isHugepagesAvailable() ? "\x1B[01;32mavailable" : "\x1B[01;31munavailable",
Mem::isHugepagesEnabled() ? "\x1B[01;32menabled" : "\x1B[01;31mdisabled");
Log::i()->text("\x1B[01;32m * \x1B[01;37mHUGE PAGES: %s",
Mem::isHugepagesAvailable() ? "\x1B[01;32mavailable" : "\x1B[01;31munavailable");
}
else {
Log::i()->text(" * HUGE PAGES: %s, %s", Mem::isHugepagesAvailable() ? "available" : "unavailable", Mem::isHugepagesEnabled() ? "enabled" : "disabled");
Log::i()->text(" * HUGE PAGES: %s", Mem::isHugepagesAvailable() ? "available" : "unavailable");
}
# endif
}
@@ -92,38 +93,47 @@ static void print_cpu(xmrig::Config *config)
static void print_threads(xmrig::Config *config)
{
char buf[32];
if (config->affinity() != -1L) {
snprintf(buf, 32, ", affinity=0x%" PRIX64, config->affinity());
if (config->threadsMode() != xmrig::Config::Advanced) {
char buf[32];
if (config->affinity() != -1L) {
snprintf(buf, 32, ", affinity=0x%" PRIX64, config->affinity());
}
else {
buf[0] = '\0';
}
Log::i()->text(config->isColors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, %sdonate=%d%%%s" : " * THREADS: %d, %s, av=%d, %sdonate=%d%%%s",
config->threadsCount(),
config->algoName(),
config->algoVariant(),
config->isColors() && config->donateLevel() == 0 ? "\x1B[01;31m" : "",
config->donateLevel(),
buf);
}
else {
buf[0] = '\0';
Log::i()->text(config->isColors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, %sdonate=%d%%" : " * THREADS: %d, %s, %sdonate=%d%%",
config->threadsCount(),
config->algoName(),
config->isColors() && config->donateLevel() == 0 ? "\x1B[01;31m" : "",
config->donateLevel());
}
Log::i()->text(config->isColors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, %sdonate=%d%%%s" : " * THREADS: %d, %s, av=%d, %sdonate=%d%%%s",
config->threadsCount(),
config->algoName(),
config->algoVariant(),
config->isColors() && config->donateLevel() == 0 ? "\x1B[01;31m" : "",
config->donateLevel(),
buf);
}
static void print_pools(xmrig::Config *config)
{
const std::vector<Url*> &pools = config->pools();
const std::vector<Pool> &pools = config->pools();
for (size_t i = 0; i < pools.size(); ++i) {
Log::i()->text(config->isColors() ? "\x1B[01;32m * \x1B[01;37mPOOL #%d: \x1B[01;36m%s:%d" : " * POOL #%d: %s:%d",
Log::i()->text(config->isColors() ? "\x1B[01;32m * \x1B[01;37mPOOL #%d: \x1B[01;36m%s" : " * POOL #%d: %s",
i + 1,
pools[i]->host(),
pools[i]->port());
pools[i].url()
);
}
# ifdef APP_DEBUG
for (size_t i = 0; i < pools.size(); ++i) {
Log::i()->text("%s:%d, user: %s, pass: %s, ka: %d, nicehash: %d", pools[i]->host(), pools[i]->port(), pools[i]->user(), pools[i]->password(), pools[i]->isKeepAlive(), pools[i]->isNicehash());
Log::i()->text("%s:%d, user: %s, pass: %s, ka: %d, nicehash: %d", pools[i].host(), pools[i].port(), pools[i].user(), pools[i].password(), pools[i].keepAlive(), pools[i].isNicehash());
}
# endif
}

View File

@@ -26,8 +26,8 @@
#include "api/Api.h"
#include "api/ApiRouter.h"
#include "api/HttpReply.h"
#include "api/HttpRequest.h"
#include "common/api/HttpReply.h"
#include "common/api/HttpRequest.h"
ApiRouter *Api::m_router = nullptr;
@@ -62,16 +62,6 @@ void Api::exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply)
}
void Api::tick(const Hashrate *hashrate)
{
if (!m_router) {
return;
}
m_router->tick(hashrate);
}
void Api::tick(const NetworkState &network)
{
if (!m_router) {

View File

@@ -47,7 +47,6 @@ public:
static void release();
static void exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply);
static void tick(const Hashrate *hashrate);
static void tick(const NetworkState &results);
private:

View File

@@ -33,20 +33,21 @@
#include "api/ApiRouter.h"
#include "api/HttpReply.h"
#include "api/HttpRequest.h"
#include "common/api/HttpReply.h"
#include "common/api/HttpRequest.h"
#include "common/Platform.h"
#include "core/Config.h"
#include "core/Controller.h"
#include "Cpu.h"
#include "interfaces/IThread.h"
#include "Mem.h"
#include "net/Job.h"
#include "Platform.h"
#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"
#include "version.h"
#include "workers/Hashrate.h"
#include "workers/Workers.h"
extern "C"
@@ -68,10 +69,6 @@ static inline double normalize(double d)
ApiRouter::ApiRouter(xmrig::Controller *controller) :
m_controller(controller)
{
m_threads = controller->config()->threadsCount();
m_hashrate = new double[m_threads * 3]();
memset(m_totalHashrate, 0, sizeof(m_totalHashrate));
memset(m_workerId, 0, sizeof(m_workerId));
setWorkerId(controller->config()->apiWorkerId());
@@ -81,7 +78,6 @@ ApiRouter::ApiRouter(xmrig::Controller *controller) :
ApiRouter::~ApiRouter()
{
delete [] m_hashrate;
}
@@ -129,21 +125,6 @@ void ApiRouter::exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply)
}
void ApiRouter::tick(const Hashrate *hashrate)
{
for (int i = 0; i < m_threads; ++i) {
m_hashrate[i * 3] = hashrate->calc((size_t) i, Hashrate::ShortInterval);
m_hashrate[i * 3 + 1] = hashrate->calc((size_t) i, Hashrate::MediumInterval);
m_hashrate[i * 3 + 2] = hashrate->calc((size_t) i, Hashrate::LargeInterval);
}
m_totalHashrate[0] = hashrate->calc(Hashrate::ShortInterval);
m_totalHashrate[1] = hashrate->calc(Hashrate::MediumInterval);
m_totalHashrate[2] = hashrate->calc(Hashrate::LargeInterval);
m_highestHashrate = hashrate->highest();
}
void ApiRouter::tick(const NetworkState &network)
{
m_network = network;
@@ -225,21 +206,23 @@ void ApiRouter::getHashrate(rapidjson::Document &doc) const
rapidjson::Value total(rapidjson::kArrayType);
rapidjson::Value threads(rapidjson::kArrayType);
for (int i = 0; i < 3; ++i) {
total.PushBack(normalize(m_totalHashrate[i]), allocator);
}
const Hashrate *hr = Workers::hashrate();
for (int i = 0; i < m_threads * 3; i += 3) {
total.PushBack(normalize(hr->calc(Hashrate::ShortInterval)), allocator);
total.PushBack(normalize(hr->calc(Hashrate::MediumInterval)), allocator);
total.PushBack(normalize(hr->calc(Hashrate::LargeInterval)), allocator);
for (size_t i = 0; i < Workers::threads(); i++) {
rapidjson::Value thread(rapidjson::kArrayType);
thread.PushBack(normalize(m_hashrate[i]), allocator);
thread.PushBack(normalize(m_hashrate[i + 1]), allocator);
thread.PushBack(normalize(m_hashrate[i + 2]), allocator);
thread.PushBack(normalize(hr->calc(i, Hashrate::ShortInterval)), allocator);
thread.PushBack(normalize(hr->calc(i, Hashrate::MediumInterval)), allocator);
thread.PushBack(normalize(hr->calc(i, Hashrate::LargeInterval)), allocator);
threads.PushBack(thread, allocator);
}
hashrate.AddMember("total", total, allocator);
hashrate.AddMember("highest", normalize(m_highestHashrate), allocator);
hashrate.AddMember("total", total, allocator);
hashrate.AddMember("highest", normalize(hr->highest()), allocator);
hashrate.AddMember("threads", threads, allocator);
doc.AddMember("hashrate", hashrate, allocator);
}
@@ -267,7 +250,7 @@ void ApiRouter::getMiner(rapidjson::Document &doc) const
doc.AddMember("ua", rapidjson::StringRef(Platform::userAgent()), allocator);
doc.AddMember("cpu", cpu, allocator);
doc.AddMember("algo", rapidjson::StringRef(m_controller->config()->algoName()), allocator);
doc.AddMember("hugepages", Mem::isHugepagesEnabled(), allocator);
doc.AddMember("hugepages", Workers::hugePages() > 0, allocator);
doc.AddMember("donate_level", m_controller->config()->donateLevel(), allocator);
}
@@ -298,13 +281,28 @@ void ApiRouter::getResults(rapidjson::Document &doc) const
void ApiRouter::getThreads(rapidjson::Document &doc) const
{
doc.SetArray();
doc.SetObject();
auto &allocator = doc.GetAllocator();
const Hashrate *hr = Workers::hashrate();
Workers::threadsSummary(doc);
const std::vector<xmrig::IThread *> &threads = m_controller->config()->threads();
rapidjson::Value list(rapidjson::kArrayType);
for (const xmrig::IThread *thread : threads) {
doc.PushBack(thread->toAPI(doc), doc.GetAllocator());
rapidjson::Value value = thread->toAPI(doc);
rapidjson::Value hashrate(rapidjson::kArrayType);
hashrate.PushBack(normalize(hr->calc(thread->index(), Hashrate::ShortInterval)), allocator);
hashrate.PushBack(normalize(hr->calc(thread->index(), Hashrate::MediumInterval)), allocator);
hashrate.PushBack(normalize(hr->calc(thread->index(), Hashrate::LargeInterval)), allocator);
value.AddMember("hashrate", hashrate, allocator);
list.PushBack(value, allocator);
}
doc.AddMember("threads", list, allocator);
}

View File

@@ -49,7 +49,6 @@ public:
void get(const xmrig::HttpRequest &req, xmrig::HttpReply &reply) const;
void exec(const xmrig::HttpRequest &req, xmrig::HttpReply &reply);
void tick(const Hashrate *hashrate);
void tick(const NetworkState &results);
protected:
@@ -69,10 +68,6 @@ private:
char m_id[17];
char m_workerId[128];
double *m_hashrate;
double m_highestHashrate;
double m_totalHashrate[3];
int m_threads;
NetworkState m_network;
xmrig::Controller *m_controller;
};

View File

@@ -29,16 +29,16 @@
#include "Platform.h"
char *Platform::m_defaultConfigName = nullptr;
char *Platform::m_userAgent = nullptr;
char Platform::m_defaultConfigName[520] = { 0 };
xmrig::c_str Platform::m_userAgent;
const char *Platform::defaultConfigName()
{
size_t size = 520;
if (m_defaultConfigName == nullptr) {
m_defaultConfigName = new char[size];
if (*m_defaultConfigName) {
return m_defaultConfigName;
}
if (uv_exepath(m_defaultConfigName, &size) < 0) {
@@ -58,5 +58,6 @@ const char *Platform::defaultConfigName()
}
}
*m_defaultConfigName = '\0';
return nullptr;
}

View File

@@ -25,20 +25,26 @@
#define __PLATFORM_H__
#include <stdint.h>
#include "common/utils/c_str.h"
class Platform
{
public:
static bool setThreadAffinity(uint64_t cpu_id);
static const char *defaultConfigName();
static void init(const char *userAgent);
static void release();
static void setProcessPriority(int priority);
static void setThreadPriority(int priority);
static inline const char *userAgent() { return m_userAgent; }
static inline const char *userAgent() { return m_userAgent.data(); }
private:
static char *m_defaultConfigName;
static char *m_userAgent;
static char m_defaultConfigName[520];
static xmrig::c_str m_userAgent;
};

View File

@@ -22,6 +22,8 @@
*/
#include <mach/thread_act.h>
#include <mach/thread_policy.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
@@ -53,15 +55,24 @@ static inline char *createUserAgent()
}
void Platform::init(const char *userAgent)
bool Platform::setThreadAffinity(uint64_t cpu_id)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
thread_port_t mach_thread;
thread_affinity_policy_data_t policy = { static_cast<integer_t>(cpu_id) };
mach_thread = pthread_mach_thread_np(pthread_self());
return thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&policy, 1) == KERN_SUCCESS;
}
void Platform::release()
void Platform::init(const char *userAgent)
{
delete [] m_userAgent;
if (userAgent) {
m_userAgent = userAgent;
}
else {
m_userAgent = createUserAgent();
}
}

View File

@@ -21,6 +21,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef __FreeBSD__
# include <sys/types.h>
# include <sys/param.h>
# include <sys/cpuset.h>
# include <pthread_np.h>
#endif
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
@@ -37,6 +45,11 @@
#endif
#ifdef __FreeBSD__
typedef cpuset_t cpu_set_t;
#endif
static inline char *createUserAgent()
{
const size_t max = 160;
@@ -63,15 +76,28 @@ static inline char *createUserAgent()
}
void Platform::init(const char *userAgent)
bool Platform::setThreadAffinity(uint64_t cpu_id)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
cpu_set_t mn;
CPU_ZERO(&mn);
CPU_SET(cpu_id, &mn);
# ifndef __ANDROID__
return pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &mn) == 0;
# else
return sched_setaffinity(gettid(), sizeof(cpu_set_t), &mn) == 0;
# endif
}
void Platform::release()
void Platform::init(const char *userAgent)
{
delete [] m_userAgent;
if (userAgent) {
m_userAgent = userAgent;
}
else {
m_userAgent = createUserAgent();
}
}

View File

@@ -27,9 +27,11 @@
#include <uv.h>
#include "log/Log.h"
#include "Platform.h"
#include "version.h"
#ifdef XMRIG_NVIDIA_PROJECT
# include "nvidia/cryptonight.h"
#endif
@@ -82,16 +84,24 @@ static inline char *createUserAgent()
}
void Platform::init(const char *userAgent)
bool Platform::setThreadAffinity(uint64_t cpu_id)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
if (cpu_id >= 64) {
LOG_ERR("Unable to set affinity. Windows supports only affinity up to 63.");
}
return SetThreadAffinityMask(GetCurrentThread(), 1ULL << cpu_id) != 0;
}
void Platform::release()
void Platform::init(const char *userAgent)
{
delete [] m_defaultConfigName;
delete [] m_userAgent;
if (userAgent) {
m_userAgent = userAgent;
}
else {
m_userAgent = createUserAgent();
}
}
@@ -131,7 +141,6 @@ void Platform::setProcessPriority(int priority)
}
void Platform::setThreadPriority(int priority)
{
if (priority == -1) {

View File

@@ -25,9 +25,9 @@
#include <microhttpd.h>
#include <string.h>
#include "api/HttpBody.h"
#include "api/HttpRequest.h"
#include "api/HttpReply.h"
#include "common/api/HttpBody.h"
#include "common/api/HttpRequest.h"
#include "common/api/HttpReply.h"
#ifndef MHD_HTTP_PAYLOAD_TOO_LARGE

View File

@@ -27,43 +27,12 @@
#include "api/Api.h"
#include "api/Httpd.h"
#include "api/HttpReply.h"
#include "api/HttpRequest.h"
#include "common/api/Httpd.h"
#include "common/api/HttpReply.h"
#include "common/api/HttpRequest.h"
#include "log/Log.h"
class UploadCtx
{
public:
inline UploadCtx() :
m_pos(0)
{}
inline bool write(const char *data, size_t size)
{
if (size > (sizeof(m_data) - m_pos - 1)) {
return false;
}
memcpy(m_data + m_pos, data, size);
m_pos += size;
m_data[m_pos] = '\0';
return true;
}
inline const char *data() const { return m_data; }
private:
char m_data[32768];
size_t m_pos;
};
Httpd::Httpd(int port, const char *accessToken, bool IPv6, bool restricted) :
m_idle(true),
m_IPv6(IPv6),

View File

@@ -22,55 +22,44 @@
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <uv.h>
#include "core/CommonConfig.h"
#include "common/config/CommonConfig.h"
#include "donate.h"
#include "log/Log.h"
#include "net/Url.h"
#include "net/Pool.h"
#include "rapidjson/document.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/prettywriter.h"
#include "xmrig.h"
static const char *algoNames[] = {
"cryptonight",
"cryptonight-lite",
"cryptonight-heavy"
};
#if defined(_WIN32) && !defined(strcasecmp)
# define strcasecmp _stricmp
#endif
xmrig::CommonConfig::CommonConfig() :
m_algorithm(CRYPTONIGHT),
m_adjusted(false),
m_apiIPv6(true),
m_apiIPv6(false),
m_apiRestricted(true),
m_background(false),
m_colors(true),
m_syslog(false),
# ifdef XMRIG_PROXY_PROJECT
m_watch(true),
# else
m_watch(false), // TODO: enable config file watch by default when this feature propertly handled and tested.
m_apiToken(nullptr),
m_apiWorkerId(nullptr),
m_fileName(nullptr),
m_logFile(nullptr),
m_userAgent(nullptr),
# endif
m_apiPort(0),
m_donateLevel(kDefaultDonateLevel),
m_printTime(60),
m_retries(5),
m_retryPause(5)
{
m_pools.push_back(new Url());
m_pools.push_back(Pool());
# ifdef XMRIG_PROXY_PROJECT
m_retries = 2;
@@ -81,23 +70,6 @@ xmrig::CommonConfig::CommonConfig() :
xmrig::CommonConfig::~CommonConfig()
{
for (Url *url : m_pools) {
delete url;
}
m_pools.clear();
free(m_fileName);
free(m_apiToken);
free(m_apiWorkerId);
free(m_logFile);
free(m_userAgent);
}
const char *xmrig::CommonConfig::algoName(Algo algorithm)
{
return algoNames[algorithm];
}
@@ -109,8 +81,8 @@ bool xmrig::CommonConfig::adjust()
m_adjusted = true;
for (Url *url : m_pools) {
url->adjust(algorithm());
for (Pool &pool : m_pools) {
pool.adjust(algorithm());
}
return true;
@@ -119,7 +91,7 @@ bool xmrig::CommonConfig::adjust()
bool xmrig::CommonConfig::isValid() const
{
return m_pools[0]->isValid();
return m_pools[0].isValid() && m_algorithm != INVALID_ALGO;
}
@@ -135,12 +107,12 @@ bool xmrig::CommonConfig::parseBoolean(int key, bool enable)
break;
case KeepAliveKey: /* --keepalive */
m_pools.back()->setKeepAlive(enable ? Url::kKeepAliveTimeout : 0);
m_pools.back().setKeepAlive(enable ? Pool::kKeepAliveTimeout : 0);
break;
# ifndef XMRIG_PROXY_PROJECT
case NicehashKey: /* --nicehash */
m_pools.back()->setNicehash(enable);
m_pools.back().setNicehash(enable);
break;
# endif
@@ -174,58 +146,52 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg)
break;
case UserpassKey: /* --userpass */
if (!m_pools.back()->setUserpass(arg)) {
if (!m_pools.back().setUserpass(arg)) {
return false;
}
break;
case UrlKey: /* --url */
if (m_pools.size() > 1 || m_pools[0]->isValid()) {
Url *url = new Url(arg);
if (url->isValid()) {
m_pools.push_back(url);
}
else {
delete url;
if (m_pools.size() > 1 || m_pools[0].isValid()) {
Pool pool(arg);
if (pool.isValid()) {
m_pools.push_back(std::move(pool));
}
}
else {
m_pools[0]->parse(arg);
m_pools[0].parse(arg);
}
if (!m_pools.back()->isValid()) {
if (!m_pools.back().isValid()) {
return false;
}
break;
case UserKey: /* --user */
m_pools.back()->setUser(arg);
m_pools.back().setUser(arg);
break;
case PasswordKey: /* --pass */
m_pools.back()->setPassword(arg);
m_pools.back().setPassword(arg);
break;
case LogFileKey: /* --log-file */
free(m_logFile);
m_logFile = strdup(arg);
m_logFile = arg;
break;
case ApiAccessTokenKey: /* --api-access-token */
free(m_apiToken);
m_apiToken = strdup(arg);
m_apiToken = arg;
break;
case ApiWorkerIdKey: /* --api-worker-id */
free(m_apiWorkerId);
m_apiWorkerId = strdup(arg);
m_apiWorkerId = arg;
break;
case UserAgentKey: /* --user-agent */
free(m_userAgent);
m_userAgent = strdup(arg);
m_userAgent = arg;
break;
case RetriesKey: /* --retries */
@@ -239,24 +205,22 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg)
case SyslogKey: /* --syslog */
case KeepAliveKey: /* --keepalive */
case NicehashKey: /* --nicehash */
case ApiIPv6Key: /* --api-ipv6 */
return parseBoolean(key, true);
case ColorKey: /* --no-color */
case WatchKey: /* --no-watch */
case ApiRestrictedKey: /* --api-no-restricted */
case ApiIPv6Key: /* --api-no-ipv6 */
return parseBoolean(key, false);
# ifdef XMRIG_PROXY_PROJECT
case 1003: /* --donate-level */
case DonateLevelKey: /* --donate-level */
# ifdef XMRIG_PROXY_PROJECT
if (strncmp(arg, "minemonero.pro", 14) == 0) {
m_donateLevel = 0;
return true;
}
else {
parseUint64(key, strtol(arg, nullptr, 10));
}
break;
# endif
# endif
return parseUint64(key, strtol(arg, nullptr, 10));
default:
break;
@@ -274,12 +238,12 @@ bool xmrig::CommonConfig::parseUint64(int key, uint64_t arg)
bool xmrig::CommonConfig::save()
{
if (!m_fileName) {
if (m_fileName.isNull()) {
return false;
}
uv_fs_t req;
const int fd = uv_fs_open(uv_default_loop(), &req, m_fileName, O_WRONLY | O_CREAT | O_TRUNC, 0644, nullptr);
const int fd = uv_fs_open(uv_default_loop(), &req, m_fileName.data(), O_WRONLY | O_CREAT | O_TRUNC, 0644, nullptr);
if (fd < 0) {
return false;
}
@@ -301,15 +265,14 @@ bool xmrig::CommonConfig::save()
uv_fs_close(uv_default_loop(), &req, fd, nullptr);
uv_fs_req_cleanup(&req);
LOG_NOTICE("configuration saved to: \"%s\"", m_fileName);
LOG_NOTICE("configuration saved to: \"%s\"", m_fileName.data());
return true;
}
void xmrig::CommonConfig::setFileName(const char *fileName)
{
free(m_fileName);
m_fileName = fileName ? strdup(fileName) : nullptr;
m_fileName = fileName;
}
@@ -329,15 +292,15 @@ bool xmrig::CommonConfig::parseInt(int key, int arg)
break;
case KeepAliveKey: /* --keepalive */
m_pools.back()->setKeepAlive(arg);
m_pools.back().setKeepAlive(arg);
break;
case VariantKey: /* --variant */
m_pools.back()->setVariant(arg);
m_pools.back().setVariant(arg);
break;
case DonateLevelKey: /* --donate-level */
if (arg >= kMinDonateLevel && arg <= 99) {
if (arg >= kMinimumDonateLevel && arg <= 99) {
m_donateLevel = arg;
}
break;
@@ -364,19 +327,5 @@ bool xmrig::CommonConfig::parseInt(int key, int arg)
void xmrig::CommonConfig::setAlgo(const char *algo)
{
if (strcasecmp(algo, "cryptonight-light") == 0) {
fprintf(stderr, "Algorithm \"cryptonight-light\" is deprecated, use \"cryptonight-lite\" instead\n");
m_algorithm = CRYPTONIGHT_LITE;
return;
}
const size_t size = sizeof(algoNames) / sizeof((algoNames)[0]);
for (size_t i = 0; i < size; i++) {
if (algoNames[i] && strcasecmp(algo, algoNames[i]) == 0) {
m_algorithm = static_cast<Algo>(i);
break;
}
}
m_algorithm = Pool::algorithm(algo);
}

View File

@@ -28,11 +28,10 @@
#include <vector>
#include "common/utils/c_str.h"
#include "common/xmrig.h"
#include "interfaces/IConfig.h"
#include "xmrig.h"
class Url;
#include "net/Pool.h"
namespace xmrig {
@@ -44,20 +43,18 @@ public:
CommonConfig();
~CommonConfig();
static const char *algoName(Algo algorithm);
inline Algo algorithm() const { return m_algorithm; }
inline bool isApiIPv6() const { return m_apiIPv6; }
inline bool isApiRestricted() const { return m_apiRestricted; }
inline bool isBackground() const { return m_background; }
inline bool isColors() const { return m_colors; }
inline bool isSyslog() const { return m_syslog; }
inline const char *algoName() const { return algoName(m_algorithm); }
inline const char *apiToken() const { return m_apiToken; }
inline const char *apiWorkerId() const { return m_apiWorkerId; }
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 const char *algoName() const { return Pool::algoName(m_algorithm); }
inline const char *apiToken() const { return m_apiToken.data(); }
inline const char *apiWorkerId() const { return m_apiWorkerId.data(); }
inline const char *logFile() const { return m_logFile.data(); }
inline const char *userAgent() const { return m_userAgent.data(); }
inline const std::vector<Pool> &pools() const { return m_pools; }
inline int apiPort() const { return m_apiPort; }
inline int donateLevel() const { return m_donateLevel; }
inline int printTime() const { return m_printTime; }
@@ -65,8 +62,8 @@ public:
inline int retryPause() const { return m_retryPause; }
inline void setColors(bool colors) { m_colors = colors; }
inline bool isWatch() const override { return m_watch && m_fileName; }
inline const char *fileName() const override { return m_fileName; }
inline bool isWatch() const override { return m_watch && !m_fileName.isNull(); }
inline const char *fileName() const override { return m_fileName.data(); }
protected:
bool adjust() override;
@@ -85,17 +82,17 @@ protected:
bool m_colors;
bool m_syslog;
bool m_watch;
char *m_apiToken;
char *m_apiWorkerId;
char *m_fileName;
char *m_logFile;
char *m_userAgent;
int m_apiPort;
int m_donateLevel;
int m_printTime;
int m_retries;
int m_retryPause;
std::vector<Url*> m_pools;
std::vector<Pool> m_pools;
xmrig::c_str m_apiToken;
xmrig::c_str m_apiWorkerId;
xmrig::c_str m_fileName;
xmrig::c_str m_logFile;
xmrig::c_str m_userAgent;
private:
bool parseInt(int key, int arg);

View File

@@ -32,14 +32,14 @@
#endif
#include "common/config/ConfigLoader.h"
#include "common/config/ConfigWatcher.h"
#include "common/Platform.h"
#include "core/ConfigCreator.h"
#include "core/ConfigLoader.h"
#include "core/ConfigLoader_platform.h"
#include "core/ConfigWatcher.h"
#include "interfaces/IConfig.h"
#include "interfaces/IWatcherListener.h"
#include "net/Url.h"
#include "Platform.h"
#include "net/Pool.h"
#include "rapidjson/document.h"
#include "rapidjson/error/en.h"
#include "rapidjson/filereadstream.h"
@@ -168,7 +168,7 @@ xmrig::IConfig *xmrig::ConfigLoader::load(int argc, char **argv, IConfigCreator
}
if (!config->isValid()) {
fprintf(stderr, "No pool URL supplied. Exiting.\n");
fprintf(stderr, "No valid configuration found. Exiting.\n");
delete config;
return nullptr;
}
@@ -293,13 +293,13 @@ void xmrig::ConfigLoader::showVersion()
printf("\n features:"
# if defined(__i386__) || defined(_M_IX86)
" i386"
" 32-bit"
# elif defined(__x86_64__) || defined(_M_AMD64)
" x86_64"
" 64-bit"
# endif
# if defined(__AES__) || defined(_MSC_VER)
" AES-NI"
" AES"
# endif
"\n");

View File

@@ -25,17 +25,17 @@
#include <stdio.h>
#include "common/config/ConfigLoader.h"
#include "common/config/ConfigWatcher.h"
#include "core/ConfigCreator.h"
#include "core/ConfigLoader.h"
#include "core/ConfigWatcher.h"
#include "interfaces/IWatcherListener.h"
#include "log/Log.h"
xmrig::ConfigWatcher::ConfigWatcher(const char *path, IConfigCreator *creator, IWatcherListener *listener) :
m_path(strdup(path)),
m_creator(creator),
m_listener(listener)
m_listener(listener),
m_path(path)
{
uv_fs_event_init(uv_default_loop(), &m_fsEvent);
uv_timer_init(uv_default_loop(), &m_timer);
@@ -50,8 +50,6 @@ xmrig::ConfigWatcher::~ConfigWatcher()
{
uv_timer_stop(&m_timer);
uv_fs_event_stop(&m_fsEvent);
free(m_path);
}
@@ -80,10 +78,10 @@ void xmrig::ConfigWatcher::queueUpdate()
void xmrig::ConfigWatcher::reload()
{
LOG_WARN("\"%s\" was changed, reloading configuration", m_path);
LOG_WARN("\"%s\" was changed, reloading configuration", m_path.data());
IConfig *config = m_creator->create();
ConfigLoader::loadFromFile(config, m_path);
ConfigLoader::loadFromFile(config, m_path.data());
if (!config->isValid()) {
LOG_ERR("reloading failed");
@@ -103,5 +101,5 @@ void xmrig::ConfigWatcher::reload()
void xmrig::ConfigWatcher::start()
{
uv_fs_event_start(&m_fsEvent, xmrig::ConfigWatcher::onFsEvent, m_path, 0);
uv_fs_event_start(&m_fsEvent, xmrig::ConfigWatcher::onFsEvent, m_path.data(), 0);
}

View File

@@ -28,6 +28,8 @@
#include <stdint.h>
#include <uv.h>
#include "common/utils/c_str.h"
#include "rapidjson/fwd.h"
@@ -56,11 +58,11 @@ private:
void reload();
void start();
char *m_path;
IConfigCreator *m_creator;
IWatcherListener *m_listener;
uv_fs_event_t m_fsEvent;
uv_timer_t m_timer;
xmrig::c_str m_path;
};

96
src/common/utils/c_str.h Normal file
View File

@@ -0,0 +1,96 @@
/* 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 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 XMRig <https://github.com/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 __C_STR_H__
#define __C_STR_H__
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
namespace xmrig {
/**
* @brief Simple C string wrapper.
*
* 1. I know about std:string.
* 2. For some reason I prefer don't use std:string in miner, eg because of file size of MSYS2 builds.
*/
class c_str
{
public:
inline c_str() : m_data(nullptr) {}
inline c_str(c_str &&other) { m_data = other.m_data; other.m_data = nullptr; }
inline c_str(const c_str &other) : m_data(nullptr) { set(other.data()); }
inline c_str(const char *str) : m_data(nullptr) { set(str); }
inline ~c_str() { free(m_data); }
inline void set(const char *str)
{
free(m_data);
m_data = str != nullptr ? strdup(str) : nullptr;
}
inline void set(char *str)
{
free(m_data);
m_data = str;
}
inline bool isEqual(const char *str) const
{
return (m_data != nullptr && str != nullptr && strcmp(m_data, str)) || (m_data == nullptr && m_data == nullptr);
}
inline bool isNull() const { return m_data == nullptr; }
inline const char *data() const { return m_data; }
inline size_t size() const { return m_data == nullptr ? 0 : strlen(m_data); }
inline bool operator!=(const c_str &str) const { return !isEqual(str.data()); }
inline bool operator!=(const char *str) const { return !isEqual(str); }
inline bool operator==(const c_str &str) const { return isEqual(str.data()); }
inline bool operator==(const char *str) const { return isEqual(str); }
inline c_str &operator=(char *str) { set(str); return *this; }
inline c_str &operator=(const c_str &str) { set(str.data()); return *this; }
inline c_str &operator=(const char *str) { set(str); return *this; }
private:
char *m_data;
};
} /* namespace xmrig */
#endif /* __C_STR_H__ */

View File

@@ -5,7 +5,6 @@
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
@@ -22,35 +21,23 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __SINGLEWORKER_H__
#define __SINGLEWORKER_H__
#ifndef __MM_MALLOC_PORTABLE_H__
#define __MM_MALLOC_PORTABLE_H__
#include "net/Job.h"
#include "net/JobResult.h"
#include "workers/Worker.h"
#ifdef _WIN32
# ifdef __GNUC__
# include <mm_malloc.h>
# else
# include <malloc.h>
# endif
#else
# if defined(XMRIG_ARM) && !defined(__clang__)
# include "aligned_malloc.h"
# else
# include <mm_malloc.h>
# endif
#endif
class Handle;
class SingleWorker : public Worker
{
public:
SingleWorker(Handle *handle);
bool start() override;
private:
bool resume(const Job &job);
bool selfTest();
void consumeJob();
void save(const Job &job);
Job m_job;
Job m_paused;
JobResult m_result;
};
#endif /* __SINGLEWORKER_H__ */
#endif /* __MM_MALLOC_PORTABLE_H__ */

View File

@@ -30,6 +30,7 @@ namespace xmrig
enum Algo {
INVALID_ALGO = -1,
CRYPTONIGHT, /* CryptoNight (Monero) */
CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */
CRYPTONIGHT_HEAVY, /* CryptoNight-Heavy (SUMO) */
@@ -63,6 +64,13 @@ enum Variant {
};
enum AesMode {
AES_AUTO,
AES_HW,
AES_SOFT
};
} /* namespace xmrig */

View File

@@ -27,6 +27,8 @@
"api": {
"port": 0, // port for the miner API https://github.com/xmrig/xmrig/wiki/API
"access-token": null, // access token for API
"worker-id": null // custom worker-id for API
"worker-id": null, // custom worker-id for API
"ipv6": false,
"restricted": true
}
}

View File

@@ -26,32 +26,29 @@
#include <inttypes.h>
#include "common/config/ConfigLoader.h"
#include "core/Config.h"
#include "core/ConfigCreator.h"
#include "core/ConfigLoader.h"
#include "Cpu.h"
#include "net/Url.h"
#include "crypto/CryptoNight_constants.h"
#include "net/Pool.h"
#include "rapidjson/document.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/prettywriter.h"
#include "workers/CpuThread.h"
#include "xmrig.h"
static char affinity_tmp[20] = { 0 };
xmrig::Config::Config() : xmrig::CommonConfig(),
m_aesMode(AES_AUTO),
m_algoVariant(AV_AUTO),
m_doubleHash(false),
m_dryRun(false),
m_hugePages(true),
m_safe(false),
m_maxCpuUsage(75),
m_printTime(60),
m_priority(-1),
m_affinity(-1L),
m_threadsCount(0)
m_priority(-1)
{
}
@@ -69,63 +66,59 @@ bool xmrig::Config::reload(const char *json)
void xmrig::Config::getJSON(rapidjson::Document &doc) const
{
using namespace rapidjson;
doc.SetObject();
auto &allocator = doc.GetAllocator();
doc.AddMember("algo", rapidjson::StringRef(algoName()), allocator);
doc.AddMember("algo", StringRef(algoName()), allocator);
rapidjson::Value api(rapidjson::kObjectType);
Value api(kObjectType);
api.AddMember("port", apiPort(), allocator);
api.AddMember("access-token", apiToken() ? rapidjson::Value(rapidjson::StringRef(apiToken())).Move() : rapidjson::Value(rapidjson::kNullType).Move(), allocator);
api.AddMember("worker-id", apiWorkerId() ? rapidjson::Value(rapidjson::StringRef(apiWorkerId())).Move() : rapidjson::Value(rapidjson::kNullType).Move(), allocator);
api.AddMember("access-token", apiToken() ? Value(StringRef(apiToken())).Move() : Value(kNullType).Move(), allocator);
api.AddMember("worker-id", apiWorkerId() ? Value(StringRef(apiWorkerId())).Move() : Value(kNullType).Move(), allocator);
api.AddMember("ipv6", isApiIPv6(), allocator);
api.AddMember("restricted", isApiRestricted(), allocator);
doc.AddMember("api", api, allocator);
doc.AddMember("av", algoVariant(), allocator);
doc.AddMember("background", isBackground(), allocator);
doc.AddMember("colors", isColors(), allocator);
doc.AddMember("colors", isColors(), allocator);
if (affinity() != -1L) {
snprintf(affinity_tmp, sizeof(affinity_tmp) - 1, "0x%" PRIX64, affinity());
doc.AddMember("cpu-affinity", rapidjson::StringRef(affinity_tmp), allocator);
doc.AddMember("cpu-affinity", StringRef(affinity_tmp), allocator);
}
else {
doc.AddMember("cpu-affinity", rapidjson::kNullType, allocator);
}
if (priority() != -1) {
doc.AddMember("cpu-priority", priority(), allocator);
}
else {
doc.AddMember("cpu-priority", rapidjson::kNullType, allocator);
doc.AddMember("cpu-affinity", kNullType, allocator);
}
doc.AddMember("cpu-priority", priority() != -1 ? Value(priority()) : Value(kNullType), allocator);
doc.AddMember("donate-level", donateLevel(), allocator);
doc.AddMember("huge-pages", isHugePages(), allocator);
doc.AddMember("log-file", logFile() ? rapidjson::Value(rapidjson::StringRef(logFile())).Move() : rapidjson::Value(rapidjson::kNullType).Move(), allocator);
doc.AddMember("hw-aes", m_aesMode == AES_AUTO ? Value(kNullType) : Value(m_aesMode == AES_HW), allocator);
doc.AddMember("log-file", logFile() ? Value(StringRef(logFile())).Move() : Value(kNullType).Move(), allocator);
doc.AddMember("max-cpu-usage", m_maxCpuUsage, allocator);
rapidjson::Value pools(rapidjson::kArrayType);
Value pools(kArrayType);
for (const Url *url : m_pools) {
rapidjson::Value obj(rapidjson::kObjectType);
for (const Pool &pool : m_pools) {
Value obj(kObjectType);
obj.AddMember("url", rapidjson::StringRef(url->url()), allocator);
obj.AddMember("user", rapidjson::StringRef(url->user()), allocator);
obj.AddMember("pass", rapidjson::StringRef(url->password()), allocator);
obj.AddMember("url", StringRef(pool.url()), allocator);
obj.AddMember("user", StringRef(pool.user()), allocator);
obj.AddMember("pass", StringRef(pool.password()), allocator);
if (url->keepAlive() == 0 || url->keepAlive() == Url::kKeepAliveTimeout) {
obj.AddMember("keepalive", url->keepAlive() > 0, allocator);
if (pool.keepAlive() == 0 || pool.keepAlive() == Pool::kKeepAliveTimeout) {
obj.AddMember("keepalive", pool.keepAlive() > 0, allocator);
}
else {
obj.AddMember("keepalive", url->keepAlive(), allocator);
obj.AddMember("keepalive", pool.keepAlive(), allocator);
}
obj.AddMember("nicehash", url->isNicehash(), allocator);
obj.AddMember("variant", url->variant(), allocator);
obj.AddMember("nicehash", pool.isNicehash(), allocator);
obj.AddMember("variant", pool.variant(), allocator);
pools.PushBack(obj, allocator);
}
@@ -135,8 +128,21 @@ void xmrig::Config::getJSON(rapidjson::Document &doc) const
doc.AddMember("retries", retries(), allocator);
doc.AddMember("retry-pause", retryPause(), allocator);
doc.AddMember("safe", m_safe, allocator);
doc.AddMember("threads", threadsCount(), allocator);
doc.AddMember("user-agent", userAgent() ? rapidjson::Value(rapidjson::StringRef(userAgent())).Move() : rapidjson::Value(rapidjson::kNullType).Move(), allocator);
if (threadsMode() == Advanced) {
Value threads(kArrayType);
for (const IThread *thread : m_threads.list) {
threads.PushBack(thread->toConfig(doc), doc.GetAllocator());
}
doc.AddMember("threads", threads, allocator);
}
else {
doc.AddMember("threads", threadsMode() == Automatic ? Value(kNullType) : Value(threadsCount()), allocator);
}
doc.AddMember("user-agent", userAgent() ? Value(StringRef(userAgent())).Move() : Value(kNullType).Move(), allocator);
# ifdef HAVE_SYSLOG_H
doc.AddMember("syslog", isSyslog(), allocator);
@@ -158,23 +164,34 @@ bool xmrig::Config::adjust()
return false;
}
m_algoVariant = getAlgoVariant();
if (m_algoVariant == AV_DOUBLE || m_algoVariant == AV_DOUBLE_SOFT) {
m_doubleHash = true;
if (!m_threads.cpu.empty()) {
m_threads.mode = Advanced;
const bool softAES = (m_aesMode == AES_AUTO ? (Cpu::hasAES() ? AES_HW : AES_SOFT) : m_aesMode) == AES_SOFT;
for (size_t i = 0; i < m_threads.cpu.size(); ++i) {
m_threads.list.push_back(CpuThread::createFromData(i, m_algorithm, m_threads.cpu[i], m_priority, softAES));
}
return true;
}
if (!m_threadsCount) {
m_threadsCount = Cpu::optimalThreadsCount(m_algorithm, m_doubleHash, m_maxCpuUsage);
m_algoVariant = getAlgoVariant();
m_threads.mode = m_threads.count ? Simple : Automatic;
const size_t size = CpuThread::multiway(m_algoVariant) * cn_select_memory(m_algorithm) / 1024;
if (!m_threads.count) {
m_threads.count = Cpu::optimalThreadsCount(size, m_maxCpuUsage);
}
else if (m_safe) {
const size_t count = Cpu::optimalThreadsCount(m_algorithm, m_doubleHash, m_maxCpuUsage);
if (m_threadsCount > count) {
m_threadsCount = count;
const size_t count = Cpu::optimalThreadsCount(size, m_maxCpuUsage);
if (m_threads.count > count) {
m_threads.count = count;
}
}
for (size_t i = 0; i < m_threadsCount; ++i) {
m_threads.push_back(CpuThread::createFromAV(i, m_algorithm, m_algoVariant, m_affinity, m_priority));
for (size_t i = 0; i < m_threads.count; ++i) {
m_threads.list.push_back(CpuThread::createFromAV(i, m_algorithm, m_algoVariant, m_threads.mask, m_priority));
}
return true;
@@ -188,18 +205,22 @@ bool xmrig::Config::parseBoolean(int key, bool enable)
}
switch (key) {
case xmrig::IConfig::SafeKey: /* --safe */
case IConfig::SafeKey: /* --safe */
m_safe = enable;
break;
case xmrig::IConfig::HugePagesKey: /* --no-huge-pages */
case IConfig::HugePagesKey: /* --no-huge-pages */
m_hugePages = enable;
break;
case xmrig::IConfig::DryRunKey: /* --dry-run */
case IConfig::DryRunKey: /* --dry-run */
m_dryRun = enable;
break;
case IConfig::HardwareAESKey: /* hw-aes config only */
m_aesMode = enable ? AES_HW : AES_SOFT;
break;
default:
break;
}
@@ -229,7 +250,7 @@ bool xmrig::Config::parseString(int key, const char *arg)
case xmrig::IConfig::ThreadsKey: /* --threads */
if (strncmp(arg, "all", 3) == 0) {
m_threadsCount = Cpu::threads();
m_threads.count = Cpu::threads();
return true;
}
@@ -258,7 +279,7 @@ bool xmrig::Config::parseUint64(int key, uint64_t arg)
switch (key) {
case xmrig::IConfig::CPUAffinityKey: /* --cpu-affinity */
if (arg) {
m_affinity = arg;
m_threads.mask = arg;
}
break;
@@ -272,6 +293,23 @@ bool xmrig::Config::parseUint64(int key, uint64_t arg)
void xmrig::Config::parseJSON(const rapidjson::Document &doc)
{
const rapidjson::Value &threads = doc["threads"];
if (threads.IsArray()) {
for (const rapidjson::Value &value : threads.GetArray()) {
if (!value.IsObject()) {
continue;
}
if (value.HasMember("low_power_mode")) {
auto data = CpuThread::parse(value);
if (data.valid) {
m_threads.cpu.push_back(std::move(data));
}
}
}
}
}
@@ -279,8 +317,8 @@ bool xmrig::Config::parseInt(int key, int arg)
{
switch (key) {
case xmrig::IConfig::ThreadsKey: /* --threads */
if (m_threadsCount >= 0 && arg < 1024) {
m_threadsCount = arg;
if (arg >= 0 && arg < 1024) {
m_threads.count = arg;
}
break;

View File

@@ -29,9 +29,10 @@
#include <vector>
#include "core/CommonConfig.h"
#include "common/config/CommonConfig.h"
#include "common/xmrig.h"
#include "rapidjson/fwd.h"
#include "xmrig.h"
#include "workers/CpuThread.h"
class Addr;
@@ -60,6 +61,13 @@ class IWatcherListener;
class Config : public CommonConfig
{
public:
enum ThreadsMode {
Automatic,
Simple,
Advanced
};
Config();
~Config();
@@ -67,15 +75,15 @@ public:
void getJSON(rapidjson::Document &doc) const override;
inline AesMode aesMode() const { return m_aesMode; }
inline AlgoVariant algoVariant() const { return m_algoVariant; }
inline bool isDoubleHash() const { return m_doubleHash; }
inline bool isDryRun() const { return m_dryRun; }
inline bool isHugePages() const { return m_hugePages; }
inline const std::vector<IThread *> &threads() const { return m_threads; }
inline int printTime() const { return m_printTime; }
inline const std::vector<IThread *> &threads() const { return m_threads.list; }
inline int priority() const { return m_priority; }
inline int threadsCount() const { return m_threadsCount; }
inline int64_t affinity() const { return m_affinity; }
inline int threadsCount() const { return m_threads.list.size(); }
inline int64_t affinity() const { return m_threads.mask; }
inline ThreadsMode threadsMode() const { return m_threads.mode; }
static Config *load(int argc, char **argv, IWatcherListener *listener);
@@ -94,17 +102,27 @@ private:
AlgoVariant getAlgoVariantLite() const;
# endif
struct Threads
{
inline Threads() : mask(-1L), count(0), mode(Automatic) {}
int64_t mask;
size_t count;
std::vector<CpuThread::Data> cpu;
std::vector<IThread *> list;
ThreadsMode mode;
};
AesMode m_aesMode;
AlgoVariant m_algoVariant;
bool m_doubleHash;
bool m_dryRun;
bool m_hugePages;
bool m_safe;
int m_maxCpuUsage;
int m_printTime;
int m_priority;
int64_t m_affinity;
size_t m_threadsCount;
std::vector<IThread *> m_threads;
Threads m_threads;
};

View File

@@ -43,7 +43,17 @@ namespace xmrig {
static char const usage[] = "\
Usage: " APP_ID " [OPTIONS]\n\
Options:\n\
-a, --algo=ALGO cryptonight (default) or cryptonight-lite\n\
-a, --algo=ALGO specify the algorithm to use\n\
cryptonight\n"
#ifndef XMRIG_NO_AEON
"\
cryptonight-lite\n"
#endif
#ifndef XMRIG_NO_SUMO
"\
cryptonight-heavy\n"
#endif
"\
-o, --url=URL URL of mining server\n\
-O, --userpass=U:P username:password pair for mining server\n\
-u, --user=USERNAME username for mining server\n\
@@ -75,6 +85,8 @@ Options:\n\
--api-port=N port for the miner API\n\
--api-access-token=T access token for API\n\
--api-worker-id=ID custom worker-id for API\n\
--api-ipv6 enable IPv6 support for API\n\
--api-no-restricted enable full remote access (only if API token set)\n\
-h, --help display this help and exit\n\
-V, --version output version information and exit\n\
";
@@ -88,7 +100,7 @@ static struct option const options[] = {
{ "api-access-token", 1, nullptr, xmrig::IConfig::ApiAccessTokenKey },
{ "api-port", 1, nullptr, xmrig::IConfig::ApiPort },
{ "api-worker-id", 1, nullptr, xmrig::IConfig::ApiWorkerIdKey },
{ "api-no-ipv6", 0, nullptr, xmrig::IConfig::ApiIPv6Key },
{ "api-ipv6", 0, nullptr, xmrig::IConfig::ApiIPv6Key },
{ "api-no-restricted", 0, nullptr, xmrig::IConfig::ApiRestrictedKey },
{ "av", 1, nullptr, xmrig::IConfig::AVKey },
{ "background", 0, nullptr, xmrig::IConfig::BackgroundKey },
@@ -140,6 +152,7 @@ static struct option const config_options[] = {
{ "syslog", 0, nullptr, xmrig::IConfig::SyslogKey },
{ "threads", 1, nullptr, xmrig::IConfig::ThreadsKey },
{ "user-agent", 1, nullptr, xmrig::IConfig::UserAgentKey },
{ "hw-aes", 0, nullptr, xmrig::IConfig::HardwareAESKey },
{ 0, 0, 0, 0 }
};

View File

@@ -25,8 +25,9 @@
#include <assert.h>
#include "common/config/ConfigLoader.h"
#include "common/Platform.h"
#include "core/Config.h"
#include "core/ConfigLoader.h"
#include "core/Controller.h"
#include "Cpu.h"
#include "interfaces/IControllerListener.h"
@@ -34,7 +35,6 @@
#include "log/FileLog.h"
#include "log/Log.h"
#include "net/Network.h"
#include "Platform.h"
#ifdef HAVE_SYSLOG_H
@@ -73,7 +73,6 @@ xmrig::Controller::Controller()
xmrig::Controller::~Controller()
{
ConfigLoader::release();
Platform::release();
delete d_ptr;
}

View File

@@ -30,18 +30,8 @@
#include <stdint.h>
#define AEON_MEMORY 1048576
#define AEON_MASK 0xFFFF0
#define AEON_ITER 0x40000
#define MONERO_MEMORY 2097152
#define MONERO_MASK 0x1FFFF0
#define MONERO_ITER 0x80000
struct cryptonight_ctx {
alignas(16) uint8_t state0[200];
alignas(16) uint8_t state1[200];
alignas(16) uint8_t state[200];
alignas(16) uint8_t* memory;
};

View File

@@ -27,13 +27,7 @@
#define __CRYPTONIGHT_ARM_H__
#if defined(XMRIG_ARM) && !defined(__clang__)
# include "aligned_malloc.h"
#else
# include <mm_malloc.h>
#endif
#include "common/utils/mm_malloc.h"
#include "crypto/CryptoNight.h"
#include "crypto/CryptoNight_constants.h"
#include "crypto/CryptoNight_monero.h"
@@ -79,6 +73,19 @@ static inline __attribute__((always_inline)) __m128i _mm_set_epi64x(const uint64
}
#ifdef XMRIG_ARMv8
static inline __attribute__((always_inline)) __m128i _mm_aesenc_si128(__m128i v, __m128i rkey)
{
alignas(16) const __m128i zero = { 0 };
return veorq_u8(vaesmcq_u8(vaeseq_u8(v, zero)), rkey );
}
#else
static inline __attribute__((always_inline)) __m128i _mm_aesenc_si128(__m128i v, __m128i rkey)
{
}
#endif
/* this one was not implemented yet so here it is */
static inline __attribute__((always_inline)) uint64_t _mm_cvtsi128_si64(__m128i a)
{
@@ -161,19 +168,19 @@ static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, _
*k0 = xout0;
*k1 = xout2;
SOFT_AES ? soft_aes_genkey_sub<0x01>(&xout0, &xout2) : soft_aes_genkey_sub<0x01>(&xout0, &xout2);
soft_aes_genkey_sub<0x01>(&xout0, &xout2);
*k2 = xout0;
*k3 = xout2;
SOFT_AES ? soft_aes_genkey_sub<0x02>(&xout0, &xout2) : soft_aes_genkey_sub<0x02>(&xout0, &xout2);
soft_aes_genkey_sub<0x02>(&xout0, &xout2);
*k4 = xout0;
*k5 = xout2;
SOFT_AES ? soft_aes_genkey_sub<0x04>(&xout0, &xout2) : soft_aes_genkey_sub<0x04>(&xout0, &xout2);
soft_aes_genkey_sub<0x04>(&xout0, &xout2);
*k6 = xout0;
*k7 = xout2;
SOFT_AES ? soft_aes_genkey_sub<0x08>(&xout0, &xout2) : soft_aes_genkey_sub<0x08>(&xout0, &xout2);
soft_aes_genkey_sub<0x08>(&xout0, &xout2);
*k8 = xout0;
*k9 = xout2;
}
@@ -192,18 +199,16 @@ static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2,
*x6 = soft_aesenc((uint32_t*)x6, key);
*x7 = soft_aesenc((uint32_t*)x7, key);
}
# ifndef XMRIG_ARMv7
else {
*x0 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x0), key));
*x1 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x1), key));
*x2 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x2), key));
*x3 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x3), key));
*x4 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x4), key));
*x5 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x5), key));
*x6 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x6), key));
*x7 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x7), key));
*x0 = _mm_aesenc_si128(*x0, key);
*x1 = _mm_aesenc_si128(*x1, key);
*x2 = _mm_aesenc_si128(*x2, key);
*x3 = _mm_aesenc_si128(*x3, key);
*x4 = _mm_aesenc_si128(*x4, key);
*x5 = _mm_aesenc_si128(*x5, key);
*x6 = _mm_aesenc_si128(*x6, key);
*x7 = _mm_aesenc_si128(*x7, key);
}
# endif
}
@@ -240,10 +245,6 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
for (size_t i = 0; i < 16; i++) {
if (!SOFT_AES) {
aes_round<SOFT_AES>(_mm_setzero_si128(), &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
}
aes_round<SOFT_AES>(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
@@ -253,30 +254,13 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
aes_round<SOFT_AES>(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
if (!SOFT_AES) {
xin0 ^= k9;
xin1 ^= k9;
xin2 ^= k9;
xin3 ^= k9;
xin4 ^= k9;
xin5 ^= k9;
xin6 ^= k9;
xin7 ^= k9;
}
else {
aes_round<SOFT_AES>(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
}
aes_round<SOFT_AES>(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
mix_and_propagate(xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7);
}
}
for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) {
if (!SOFT_AES) {
aes_round<SOFT_AES>(_mm_setzero_si128(), &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
}
aes_round<SOFT_AES>(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
@@ -286,20 +270,7 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
aes_round<SOFT_AES>(k6, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
if (!SOFT_AES) {
xin0 ^= k9;
xin1 ^= k9;
xin2 ^= k9;
xin3 ^= k9;
xin4 ^= k9;
xin5 ^= k9;
xin6 ^= k9;
xin7 ^= k9;
}
else {
aes_round<SOFT_AES>(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
}
aes_round<SOFT_AES>(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
_mm_store_si128(output + i + 0, xin0);
_mm_store_si128(output + i + 1, xin1);
@@ -341,10 +312,6 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
if (!SOFT_AES) {
aes_round<SOFT_AES>(_mm_setzero_si128(), &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
}
aes_round<SOFT_AES>(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
@@ -354,20 +321,7 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
aes_round<SOFT_AES>(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
if (!SOFT_AES) {
xout0 ^= k9;
xout1 ^= k9;
xout2 ^= k9;
xout3 ^= k9;
xout4 ^= k9;
xout5 ^= k9;
xout6 ^= k9;
xout7 ^= k9;
}
else {
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
}
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
if (ALGO == xmrig::CRYPTONIGHT_HEAVY) {
mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7);
@@ -385,10 +339,6 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
if (!SOFT_AES) {
aes_round<SOFT_AES>(_mm_setzero_si128(), &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
}
aes_round<SOFT_AES>(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
@@ -398,29 +348,12 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
aes_round<SOFT_AES>(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
if (!SOFT_AES) {
xout0 ^= k9;
xout1 ^= k9;
xout2 ^= k9;
xout3 ^= k9;
xout4 ^= k9;
xout5 ^= k9;
xout6 ^= k9;
xout7 ^= k9;
}
else {
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
}
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7);
}
for (size_t i = 0; i < 16; i++) {
if (!SOFT_AES) {
aes_round<SOFT_AES>(_mm_setzero_si128(), &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
}
aes_round<SOFT_AES>(k0, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k1, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k2, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
@@ -430,20 +363,7 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
aes_round<SOFT_AES>(k6, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
if (!SOFT_AES) {
xout0 ^= k9;
xout1 ^= k9;
xout2 ^= k9;
xout3 ^= k9;
xout4 ^= k9;
xout5 ^= k9;
xout6 ^= k9;
xout7 ^= k9;
}
else {
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
}
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
mix_and_propagate(xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7);
}
@@ -460,8 +380,23 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
}
static inline void cryptonight_monero_tweak(uint64_t* mem_out, __m128i tmp)
{
mem_out[0] = EXTRACT64(tmp);
uint64_t vh = vgetq_lane_u64(tmp, 1);
uint8_t x = vh >> 24;
static const uint16_t table = 0x7531;
const uint8_t index = (((x >> 3) & 6) | (x & 1)) << 1;
vh ^= ((table >> index) & 0x3) << 28;
mem_out[1] = vh;
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx)
{
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO>();
@@ -472,14 +407,14 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
return;
}
keccak(input, (int) size, ctx->state0, 200);
keccak(input, (int) size, ctx[0]->state, 200);
VARIANT1_INIT(0);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx->state0, (__m128i*) ctx->memory);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx[0]->state, (__m128i*) ctx[0]->memory);
const uint8_t* l0 = ctx->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx->state0);
const uint8_t* l0 = ctx[0]->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx[0]->state);
uint64_t al0 = h0[0] ^ h0[4];
uint64_t ah0 = h0[1] ^ h0[5];
@@ -495,13 +430,15 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
}
else {
cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
# ifndef XMRIG_ARMv7
cx = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0);
# endif
cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0));
}
if (VARIANT > 0) {
cryptonight_monero_tweak((uint64_t*)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
} else {
_mm_store_si128((__m128i *)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
}
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
VARIANT1_1(&l0[idx0 & MASK]);
idx0 = EXTRACT64(cx);
bx0 = cx;
@@ -532,15 +469,15 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
}
}
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx->memory, (__m128i*) ctx->state0);
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx[0]->memory, (__m128i*) ctx[0]->state);
keccakf(h0, 24);
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx **__restrict__ ctx)
{
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO>();
@@ -551,16 +488,16 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
return;
}
keccak(input, (int) size, ctx->state0, 200);
keccak(input + size, (int) size, ctx->state1, 200);
keccak(input, (int) size, ctx[0]->state, 200);
keccak(input + size, (int) size, ctx[1]->state, 200);
VARIANT1_INIT(0);
VARIANT1_INIT(1);
const uint8_t* l0 = ctx->memory;
const uint8_t* l1 = ctx->memory + MEM;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx->state0);
uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx->state1);
const uint8_t* l0 = ctx[0]->memory;
const uint8_t* l1 = ctx[1]->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx[0]->state);
uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx[1]->state);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) h0, (__m128i*) l0);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) h1, (__m128i*) l1);
@@ -586,16 +523,17 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
else {
cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]);
# ifndef XMRIG_ARMv7
cx0 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx0, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0);
cx1 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx1, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah1, al1);
# endif
cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0));
cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1));
}
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
_mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
VARIANT1_1(&l0[idx0 & MASK]);
VARIANT1_1(&l1[idx1 & MASK]);
if (VARIANT > 0) {
cryptonight_monero_tweak((uint64_t*)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
cryptonight_monero_tweak((uint64_t*)&l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
} else {
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
_mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
};
idx0 = EXTRACT64(cx0);
idx1 = EXTRACT64(cx1);
@@ -661,25 +599,25 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
keccakf(h0, 24);
keccakf(h1, 24);
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, output + 32);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
extra_hashes[ctx[1]->state[0] & 3](ctx[1]->state, 200, output + 32);
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx **__restrict__ ctx)
{
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx **__restrict__ ctx)
{
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx **__restrict__ ctx)
{
}

View File

@@ -29,7 +29,7 @@
#include <stdint.h>
#include "xmrig.h"
#include "common/xmrig.h"
namespace xmrig
@@ -65,7 +65,12 @@ inline size_t cn_select_memory(Algo algorithm)
case CRYPTONIGHT_HEAVY:
return CRYPTONIGHT_HEAVY_MEMORY;
default:
break;
}
return 0;
}
@@ -86,7 +91,12 @@ inline uint32_t cn_select_mask(Algo algorithm)
case CRYPTONIGHT_HEAVY:
return CRYPTONIGHT_HEAVY_MASK;
default:
break;
}
return 0;
}
@@ -107,7 +117,12 @@ inline uint32_t cn_select_iter(Algo algorithm)
case CRYPTONIGHT_HEAVY:
return CRYPTONIGHT_HEAVY_ITER;
default:
break;
}
return 0;
}

View File

@@ -32,14 +32,14 @@
uint64_t tweak1_2_##part = 0; \
if (VARIANT > 0) { \
tweak1_2_##part = (*reinterpret_cast<const uint64_t*>(input + 35 + part * size) ^ \
*(reinterpret_cast<const uint64_t*>(ctx->state##part) + 24)); \
*(reinterpret_cast<const uint64_t*>(ctx[part]->state) + 24)); \
}
#else
# define VARIANT1_INIT(part) \
uint64_t tweak1_2_##part = 0; \
if (VARIANT > 0) { \
volatile const uint64_t a = *reinterpret_cast<const uint64_t*>(input + 35 + part * size); \
volatile const uint64_t b = *(reinterpret_cast<const uint64_t*>(ctx->state##part) + 24); \
volatile const uint64_t b = *(reinterpret_cast<const uint64_t*>(ctx[part]->state) + 24); \
tweak1_2_##part = a ^ b; \
}
#endif

View File

@@ -26,62 +26,107 @@
#define __CRYPTONIGHT_TEST_H__
const static uint8_t test_input[152] = {
const static uint8_t test_input[380] = {
0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00,
0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B,
0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62,
0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92,
0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01,
0x01, 0x00, 0xFB, 0x8E, 0x8A, 0xC8, 0x05, 0x89, 0x93, 0x23, 0x37, 0x1B, 0xB7, 0x90, 0xDB, 0x19,
0x21, 0x8A, 0xFD, 0x8D, 0xB8, 0xE3, 0x75, 0x5D, 0x8B, 0x90, 0xF3, 0x9B, 0x3D, 0x55, 0x06, 0xA9,
0xAB, 0xCE, 0x4F, 0xA9, 0x12, 0x24, 0x45, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x81, 0x46, 0xD4, 0x9F,
0xA9, 0x3E, 0xE7, 0x24, 0xDE, 0xB5, 0x7D, 0x12, 0xCB, 0xC6, 0xC6, 0xF3, 0xB9, 0x24, 0xD9, 0x46,
0x12, 0x7C, 0x7A, 0x97, 0x41, 0x8F, 0x93, 0x48, 0x82, 0x8F, 0x0F, 0x02,
0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00,
0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B,
0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62,
0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92,
0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01
0x07, 0x07, 0xB4, 0x87, 0xD0, 0xD6, 0x05, 0x26, 0xE0, 0xC6, 0xDD, 0x9B, 0xC7, 0x18, 0xC3, 0xCF,
0x52, 0x04, 0xBD, 0x4F, 0x9B, 0x27, 0xF6, 0x73, 0xB9, 0x3F, 0xEF, 0x7B, 0xB2, 0xF7, 0x2B, 0xBB,
0x3F, 0x3E, 0x9C, 0x3E, 0x9D, 0x33, 0x1E, 0xDE, 0xAD, 0xBE, 0xEF, 0x4E, 0x00, 0x91, 0x81, 0x29,
0x74, 0xB2, 0x70, 0xE7, 0x6D, 0xD2, 0x2A, 0x5F, 0x52, 0x04, 0x93, 0xE6, 0x18, 0x89, 0x40, 0xD8,
0xC6, 0xE3, 0x90, 0x6E, 0xAA, 0x6A, 0xB7, 0xE2, 0x08, 0x7E, 0x78, 0x0E,
0x01, 0x00, 0xEE, 0xB2, 0xD1, 0xD6, 0x05, 0xFF, 0x27, 0x7F, 0x26, 0xDB, 0xAA, 0xB2, 0xC9, 0x26,
0x30, 0xC6, 0xCF, 0x11, 0x64, 0xEA, 0x6C, 0x8A, 0xE0, 0x98, 0x01, 0xF8, 0x75, 0x4B, 0x49, 0xAF,
0x79, 0x70, 0xAE, 0xEE, 0xA7, 0x62, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x47, 0x8C, 0x63, 0xE7, 0xD8,
0x40, 0x02, 0x3C, 0xDA, 0xEA, 0x92, 0x52, 0x53, 0xAC, 0xFD, 0xC7, 0x8A, 0x4C, 0x31, 0xB2, 0xF2,
0xEC, 0x72, 0x7B, 0xFF, 0xCE, 0xC0, 0xE7, 0x12, 0xD4, 0xE9, 0x2A, 0x01,
0x07, 0x07, 0xA9, 0xB7, 0xD1, 0xD6, 0x05, 0x3F, 0x0D, 0x5E, 0xFD, 0xC7, 0x03, 0xFC, 0xFC, 0xD2,
0xCE, 0xBC, 0x44, 0xD8, 0xAB, 0x44, 0xA6, 0xA0, 0x3A, 0xE4, 0x4D, 0x8F, 0x15, 0xAF, 0x62, 0x17,
0xD1, 0xE0, 0x92, 0x85, 0xE4, 0x73, 0xF9, 0x00, 0x00, 0x00, 0xA0, 0xFC, 0x09, 0xDE, 0xAB, 0xF5,
0x8B, 0x6F, 0x1D, 0xCA, 0xA8, 0xBA, 0xAC, 0x74, 0xDD, 0x74, 0x19, 0xD5, 0xD6, 0x10, 0xEC, 0x38,
0xCF, 0x50, 0x29, 0x6A, 0x07, 0x0B, 0x93, 0x8F, 0x8F, 0xA8, 0x10, 0x04
};
const static uint8_t test_output_v0[64] = {
const static uint8_t test_output_v0[160] = {
0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7,
0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00,
0x1B, 0x60, 0x6A, 0x3F, 0x4A, 0x07, 0xD6, 0x48, 0x9A, 0x1B, 0xCD, 0x07, 0x69, 0x7B, 0xD1, 0x66,
0x96, 0xB6, 0x1C, 0x8A, 0xE9, 0x82, 0xF6, 0x1A, 0x90, 0x16, 0x0F, 0x4E, 0x52, 0x82, 0x8A, 0x7F,
0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7,
0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00
0xA1, 0xB4, 0xFA, 0xE3, 0xE5, 0x76, 0xCE, 0xCF, 0xB7, 0x9C, 0xAF, 0x3E, 0x29, 0x92, 0xE4, 0xE0,
0x31, 0x24, 0x05, 0x48, 0xBF, 0x8D, 0x5F, 0x7B, 0x11, 0x03, 0x60, 0xAA, 0xD7, 0x50, 0x3F, 0x0C,
0x2D, 0x30, 0xF3, 0x87, 0x4F, 0x86, 0xA1, 0x4A, 0xB5, 0xA2, 0x1A, 0x08, 0xD0, 0x44, 0x2C, 0x9D,
0x16, 0xE9, 0x28, 0x49, 0xA1, 0xFF, 0x85, 0x6F, 0x12, 0xBB, 0x7D, 0xAB, 0x11, 0x1C, 0xE7, 0xF7,
0x2D, 0x9D, 0x19, 0xE4, 0xD2, 0x26, 0x44, 0x1E, 0xCD, 0x22, 0x08, 0x24, 0xA8, 0x97, 0x46, 0x62,
0x04, 0x84, 0x90, 0x4A, 0xEE, 0x99, 0x14, 0xED, 0xB8, 0xC6, 0x0D, 0x37, 0xA1, 0x66, 0x17, 0xB0
};
// Monero v7
const static uint8_t test_output_v1[64] = {
0xC9, 0xFA, 0xE8, 0x42, 0x5D, 0x86, 0x88, 0xDC, 0x23, 0x6B, 0xCD, 0xBC, 0x42, 0xFD, 0xB4, 0x2D,
0x37, 0x6C, 0x6E, 0xC1, 0x90, 0x50, 0x1A, 0xA8, 0x4B, 0x04, 0xA4, 0xB4, 0xCF, 0x1E, 0xE1, 0x22,
const static uint8_t test_output_v1[160] = {
0xF2, 0x2D, 0x3D, 0x62, 0x03, 0xD2, 0xA0, 0x8B, 0x41, 0xD9, 0x02, 0x72, 0x78, 0xD8, 0xBC, 0xC9,
0x83, 0xAC, 0xAD, 0xA9, 0xB6, 0x8E, 0x52, 0xE3, 0xC6, 0x89, 0x69, 0x2A, 0x50, 0xE9, 0x21, 0xD9
0x83, 0xAC, 0xAD, 0xA9, 0xB6, 0x8E, 0x52, 0xE3, 0xC6, 0x89, 0x69, 0x2A, 0x50, 0xE9, 0x21, 0xD9,
0xC9, 0xFA, 0xE8, 0x42, 0x5D, 0x86, 0x88, 0xDC, 0x23, 0x6B, 0xCD, 0xBC, 0x42, 0xFD, 0xB4, 0x2D,
0x37, 0x6C, 0x6E, 0xC1, 0x90, 0x50, 0x1A, 0xA8, 0x4B, 0x04, 0xA4, 0xB4, 0xCF, 0x1E, 0xE1, 0x22,
0xE7, 0x8C, 0x5A, 0x6E, 0x38, 0x30, 0x68, 0x4A, 0x73, 0xFC, 0x1B, 0xC6, 0x6D, 0xFC, 0x8D, 0x98,
0xB4, 0xC2, 0x23, 0x39, 0xAD, 0xE0, 0x9D, 0xF6, 0x6D, 0x8C, 0x6A, 0xAA, 0xF9, 0xB2, 0xE3, 0x4C,
0xB6, 0x90, 0x6C, 0xE6, 0x15, 0x5E, 0x46, 0x07, 0x9C, 0xB2, 0x6B, 0xAC, 0x3B, 0xAC, 0x1A, 0xDE,
0x92, 0x2C, 0xD6, 0x0C, 0x46, 0x9D, 0x9B, 0xC2, 0x84, 0x52, 0x65, 0xF6, 0xBD, 0xFA, 0x0D, 0x74,
0x00, 0x66, 0x10, 0x07, 0xF1, 0x19, 0x06, 0x3A, 0x6C, 0xFF, 0xEE, 0xB2, 0x40, 0xE5, 0x88, 0x2B,
0x6C, 0xAB, 0x6B, 0x1D, 0x88, 0xB8, 0x44, 0x25, 0xF4, 0xEA, 0xB7, 0xEC, 0xBA, 0x12, 0x8A, 0x24
};
#ifndef XMRIG_NO_AEON
const static uint8_t test_output_v0_lite[64] = {
const static uint8_t test_output_v0_lite[160] = {
0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E,
0x00, 0x4E, 0xEC, 0xE0, 0x9B, 0x83, 0xA7, 0x2E, 0xF6, 0xBA, 0x98, 0x64, 0xD3, 0x51, 0x0C, 0x88,
0x28, 0xA2, 0x2B, 0xAD, 0x3F, 0x93, 0xD1, 0x40, 0x8F, 0xCA, 0x47, 0x2E, 0xB5, 0xAD, 0x1C, 0xBE,
0x75, 0xF2, 0x1D, 0x05, 0x3C, 0x8C, 0xE5, 0xB3, 0xAF, 0x10, 0x5A, 0x57, 0x71, 0x3E, 0x21, 0xDD,
0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E,
0x00, 0x4E, 0xEC, 0xE0, 0x9B, 0x83, 0xA7, 0x2E, 0xF6, 0xBA, 0x98, 0x64, 0xD3, 0x51, 0x0C, 0x88
0x38, 0x08, 0xE1, 0x17, 0x0B, 0x99, 0x8D, 0x1A, 0x3C, 0xCE, 0x35, 0xC5, 0xC7, 0x3A, 0x00, 0x2E,
0xCB, 0x54, 0xF0, 0x78, 0x2E, 0x9E, 0xDB, 0xC7, 0xDF, 0x2E, 0x71, 0x9A, 0x16, 0x97, 0xC4, 0x18,
0x4B, 0x97, 0x07, 0xFE, 0x5D, 0x98, 0x9A, 0xD6, 0xD8, 0xE5, 0x92, 0x66, 0x87, 0x7F, 0x19, 0x37,
0xA2, 0x5E, 0xE6, 0x96, 0xB5, 0x97, 0x33, 0x89, 0xE0, 0xA7, 0xC9, 0xDD, 0x4A, 0x7E, 0x9E, 0x53,
0xBE, 0x91, 0x2B, 0xF5, 0xF5, 0xAF, 0xDD, 0x09, 0xA2, 0xF4, 0xA4, 0x56, 0xEB, 0x96, 0x22, 0xC9,
0x94, 0xFB, 0x7B, 0x28, 0xC9, 0x97, 0x65, 0x04, 0xAC, 0x4F, 0x84, 0x71, 0xDA, 0x6E, 0xD8, 0xC5
};
// AEON v7
const static uint8_t test_output_v1_lite[64] = {
const static uint8_t test_output_v1_lite[160] = {
0x6D, 0x8C, 0xDC, 0x44, 0x4E, 0x9B, 0xBB, 0xFD, 0x68, 0xFC, 0x43, 0xFC, 0xD4, 0x85, 0x5B, 0x22,
0x8C, 0x8A, 0x1B, 0xD9, 0x1D, 0x9D, 0x00, 0x28, 0x5B, 0xEC, 0x02, 0xB7, 0xCA, 0x2D, 0x67, 0x41,
0x87, 0xC4, 0xE5, 0x70, 0x65, 0x3E, 0xB4, 0xC2, 0xB4, 0x2B, 0x7A, 0x0D, 0x54, 0x65, 0x59, 0x45,
0x2D, 0xFA, 0xB5, 0x73, 0xB8, 0x2E, 0xC5, 0x2F, 0x15, 0x2B, 0x7F, 0xF9, 0x8E, 0x79, 0x44, 0x6F,
0x6D, 0x8C, 0xDC, 0x44, 0x4E, 0x9B, 0xBB, 0xFD, 0x68, 0xFC, 0x43, 0xFC, 0xD4, 0x85, 0x5B, 0x22,
0x8C, 0x8A, 0x1B, 0xD9, 0x1D, 0x9D, 0x00, 0x28, 0x5B, 0xEC, 0x02, 0xB7, 0xCA, 0x2D, 0x67, 0x41
0x16, 0x08, 0x74, 0xC7, 0xA2, 0xD2, 0xA3, 0x97, 0x95, 0x76, 0xCA, 0x4D, 0x06, 0x39, 0x7A, 0xAB,
0x6C, 0x87, 0x58, 0x33, 0x4D, 0xC8, 0x5A, 0xAB, 0x04, 0x27, 0xFE, 0x8B, 0x1C, 0x23, 0x2F, 0x32,
0xC0, 0x44, 0xFF, 0x0D, 0xB5, 0x3B, 0x27, 0x96, 0x06, 0x89, 0x7B, 0xA3, 0x0B, 0xD0, 0xCE, 0x9E,
0x90, 0x22, 0x77, 0x5A, 0xAD, 0xA1, 0xE5, 0xB6, 0xFC, 0xCB, 0x39, 0x7E, 0x2B, 0x10, 0xEE, 0xB4,
0x8C, 0x2B, 0xA4, 0x1F, 0x60, 0x76, 0x39, 0xD7, 0xF6, 0x46, 0x77, 0x18, 0x20, 0xAD, 0xD4, 0xC9,
0x87, 0xF7, 0x37, 0xDA, 0xFD, 0xBA, 0xBA, 0xD2, 0xF2, 0x68, 0xDC, 0x26, 0x8D, 0x1B, 0x08, 0xC6
};
#endif
#ifndef XMRIG_NO_SUMO
const static uint8_t test_output_heavy[64] = {
const static uint8_t test_output_heavy[160] = {
0x99, 0x83, 0xF2, 0x1B, 0xDF, 0x20, 0x10, 0xA8, 0xD7, 0x07, 0xBB, 0x2F, 0x14, 0xD7, 0x86, 0x64,
0xBB, 0xE1, 0x18, 0x7F, 0x55, 0x01, 0x4B, 0x39, 0xE5, 0xF3, 0xD6, 0x93, 0x28, 0xE4, 0x8F, 0xC2,
0x4D, 0x94, 0x7D, 0xD6, 0xDB, 0x6E, 0x07, 0x48, 0x26, 0x4A, 0x51, 0x2E, 0xAC, 0xF3, 0x25, 0x4A,
0x1F, 0x1A, 0xA2, 0x5B, 0xFC, 0x0A, 0xAD, 0x82, 0xDE, 0xA8, 0x99, 0x96, 0x88, 0x52, 0xD2, 0x7D,
0x99, 0x83, 0xF2, 0x1B, 0xDF, 0x20, 0x10, 0xA8, 0xD7, 0x07, 0xBB, 0x2F, 0x14, 0xD7, 0x86, 0x64,
0xBB, 0xE1, 0x18, 0x7F, 0x55, 0x01, 0x4B, 0x39, 0xE5, 0xF3, 0xD6, 0x93, 0x28, 0xE4, 0x8F, 0xC2
0x3E, 0xE1, 0x23, 0x03, 0x5A, 0x63, 0x7B, 0x66, 0xF6, 0xD7, 0xC2, 0x2A, 0x34, 0x5E, 0x88, 0xE7,
0xFA, 0xC4, 0x25, 0x36, 0x54, 0xCB, 0xD2, 0x5C, 0x2F, 0x80, 0x2A, 0xF9, 0xCC, 0x43, 0xF7, 0xCD,
0xE5, 0x18, 0xA8, 0x05, 0x60, 0x18, 0xA5, 0x73, 0x72, 0x9B, 0x32, 0xDC, 0x69, 0x83, 0xC1, 0xE1,
0x1F, 0xDB, 0xDA, 0x6B, 0xAC, 0xEC, 0x9F, 0x67, 0xF8, 0x27, 0x1D, 0xC7, 0xE6, 0x46, 0x42, 0xF9,
0x53, 0x62, 0x0A, 0x54, 0x7D, 0x43, 0xEA, 0x18, 0x94, 0xED, 0xD8, 0x92, 0x06, 0x6A, 0xA1, 0x51,
0xAD, 0xB1, 0xFD, 0x89, 0xFB, 0x5C, 0xB4, 0x25, 0x6A, 0xDD, 0xB0, 0x09, 0xC5, 0x72, 0x87, 0xEB
};
#endif

View File

@@ -386,8 +386,24 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
}
static inline void cryptonight_monero_tweak(uint64_t* mem_out, __m128i tmp)
{
mem_out[0] = EXTRACT64(tmp);
tmp = _mm_castps_si128(_mm_movehl_ps(_mm_castsi128_ps(tmp), _mm_castsi128_ps(tmp)));
uint64_t vh = EXTRACT64(tmp);
uint8_t x = vh >> 24;
static const uint16_t table = 0x7531;
const uint8_t index = (((x >> 3) & 6) | (x & 1)) << 1;
vh ^= ((table >> index) & 0x3) << 28;
mem_out[1] = vh;
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx)
{
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO>();
@@ -398,20 +414,20 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
return;
}
keccak(input, (int) size, ctx->state0, 200);
keccak(input, (int) size, ctx[0]->state, 200);
VARIANT1_INIT(0);
VARIANT1_INIT(0)
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx->state0, (__m128i*) ctx->memory);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx[0]->state, (__m128i*) ctx[0]->memory);
const uint8_t* l0 = ctx->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx->state0);
const uint8_t* l0 = ctx[0]->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx[0]->state);
uint64_t al0 = h0[0] ^ h0[4];
uint64_t ah0 = h0[1] ^ h0[5];
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
uint64_t idx0 = h0[0] ^ h0[4];
uint64_t idx0 = al0;
for (size_t i = 0; i < ITERATIONS; i++) {
__m128i cx;
@@ -423,8 +439,13 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0));
}
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
VARIANT1_1(&l0[idx0 & MASK]);
if (VARIANT > 0) {
cryptonight_monero_tweak((uint64_t*)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
} else {
_mm_store_si128((__m128i *)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
}
idx0 = EXTRACT64(cx);
bx0 = cx;
@@ -455,15 +476,15 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si
}
}
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx->memory, (__m128i*) ctx->state0);
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) ctx[0]->memory, (__m128i*) ctx[0]->state);
keccakf(h0, 24);
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx)
{
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO>();
@@ -474,16 +495,16 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
return;
}
keccak(input, (int) size, ctx->state0, 200);
keccak(input + size, (int) size, ctx->state1, 200);
keccak(input, (int) size, ctx[0]->state, 200);
keccak(input + size, (int) size, ctx[1]->state, 200);
VARIANT1_INIT(0);
VARIANT1_INIT(1);
const uint8_t* l0 = ctx->memory;
const uint8_t* l1 = ctx->memory + MEM;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx->state0);
uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx->state1);
const uint8_t* l0 = ctx[0]->memory;
const uint8_t* l1 = ctx[1]->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx[0]->state);
uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx[1]->state);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) h0, (__m128i*) l0);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>((__m128i*) h1, (__m128i*) l1);
@@ -496,8 +517,8 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
__m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
uint64_t idx0 = h0[0] ^ h0[4];
uint64_t idx1 = h1[0] ^ h1[4];
uint64_t idx0 = al0;
uint64_t idx1 = al1;
for (size_t i = 0; i < ITERATIONS; i++) {
__m128i cx0, cx1;
@@ -513,10 +534,13 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1));
}
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
_mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
VARIANT1_1(&l0[idx0 & MASK]);
VARIANT1_1(&l1[idx1 & MASK]);
if (VARIANT > 0) {
cryptonight_monero_tweak((uint64_t*)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
cryptonight_monero_tweak((uint64_t*)&l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
} else {
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
_mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
}
idx0 = EXTRACT64(cx0);
idx1 = EXTRACT64(cx1);
@@ -582,26 +606,382 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si
keccakf(h0, 24);
keccakf(h1, 24);
extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, output);
extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, output + 32);
extra_hashes[ctx[0]->state[0] & 3](ctx[0]->state, 200, output);
extra_hashes[ctx[1]->state[0] & 3](ctx[1]->state, 200, output + 32);
}
#define CN_STEP1(a, b, c, l, ptr, idx) \
ptr = reinterpret_cast<__m128i*>(&l[idx & MASK]); \
c = _mm_load_si128(ptr);
#define CN_STEP2(a, b, c, l, ptr, idx) \
if (SOFT_AES) { \
c = soft_aesenc(c, a); \
} else { \
c = _mm_aesenc_si128(c, a); \
} \
\
b = _mm_xor_si128(b, c); \
\
if (VARIANT > 0) { \
cryptonight_monero_tweak(reinterpret_cast<uint64_t*>(ptr), b); \
} else { \
_mm_store_si128(ptr, b); \
}
#define CN_STEP3(a, b, c, l, ptr, idx) \
idx = EXTRACT64(c); \
ptr = reinterpret_cast<__m128i*>(&l[idx & MASK]); \
b = _mm_load_si128(ptr);
#define CN_STEP4(a, b, c, l, mc, ptr, idx) \
lo = __umul128(idx, EXTRACT64(b), &hi); \
a = _mm_add_epi64(a, _mm_set_epi64x(lo, hi)); \
\
if (VARIANT > 0) { \
_mm_store_si128(ptr, _mm_xor_si128(a, mc)); \
} else { \
_mm_store_si128(ptr, a); \
} \
\
a = _mm_xor_si128(a, b); \
idx = EXTRACT64(a); \
\
if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { \
int64_t n = ((int64_t*)&l[idx & MASK])[0]; \
int32_t d = ((int32_t*)&l[idx & MASK])[2]; \
int64_t q = n / (d | 0x5); \
((int64_t*)&l[idx & MASK])[0] = n ^ q; \
idx = d ^ q; \
}
#define CONST_INIT(ctx, n) \
__m128i mc##n; \
if (VARIANT > 0) { \
mc##n = _mm_set_epi64x(*reinterpret_cast<const uint64_t*>(input + n * size + 35) ^ \
*(reinterpret_cast<const uint64_t*>((ctx)->state) + 24), 0); \
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx)
{
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO>();
constexpr size_t MEM = xmrig::cn_select_memory<ALGO>();
if (VARIANT > 0 && size < 43) {
memset(output, 0, 32 * 3);
return;
}
for (size_t i = 0; i < 3; i++) {
keccak(input + size * i, static_cast<int>(size), ctx[i]->state, 200);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->state), reinterpret_cast<__m128i*>(ctx[i]->memory));
}
CONST_INIT(ctx[0], 0);
CONST_INIT(ctx[1], 1);
CONST_INIT(ctx[2], 2);
uint8_t* l0 = ctx[0]->memory;
uint8_t* l1 = ctx[1]->memory;
uint8_t* l2 = ctx[2]->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx[0]->state);
uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx[1]->state);
uint64_t* h2 = reinterpret_cast<uint64_t*>(ctx[2]->state);
__m128i ax0 = _mm_set_epi64x(h0[1] ^ h0[5], h0[0] ^ h0[4]);
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
__m128i ax1 = _mm_set_epi64x(h1[1] ^ h1[5], h1[0] ^ h1[4]);
__m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
__m128i ax2 = _mm_set_epi64x(h2[1] ^ h2[5], h2[0] ^ h2[4]);
__m128i bx2 = _mm_set_epi64x(h2[3] ^ h2[7], h2[2] ^ h2[6]);
__m128i cx0 = _mm_set_epi64x(0, 0);
__m128i cx1 = _mm_set_epi64x(0, 0);
__m128i cx2 = _mm_set_epi64x(0, 0);
uint64_t idx0, idx1, idx2;
idx0 = EXTRACT64(ax0);
idx1 = EXTRACT64(ax1);
idx2 = EXTRACT64(ax2);
for (size_t i = 0; i < ITERATIONS / 2; i++) {
uint64_t hi, lo;
__m128i *ptr0, *ptr1, *ptr2;
// EVEN ROUND
CN_STEP1(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP1(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP1(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP2(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP2(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP2(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP3(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP3(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP3(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP4(ax0, bx0, cx0, l0, mc0, ptr0, idx0);
CN_STEP4(ax1, bx1, cx1, l1, mc1, ptr1, idx1);
CN_STEP4(ax2, bx2, cx2, l2, mc2, ptr2, idx2);
// ODD ROUND
CN_STEP1(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP1(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP1(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP2(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP2(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP2(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP3(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP3(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP3(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP4(ax0, cx0, bx0, l0, mc0, ptr0, idx0);
CN_STEP4(ax1, cx1, bx1, l1, mc1, ptr1, idx1);
CN_STEP4(ax2, cx2, bx2, l2, mc2, ptr2, idx2);
}
for (size_t i = 0; i < 3; i++) {
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->memory), reinterpret_cast<__m128i*>(ctx[i]->state));
keccakf(reinterpret_cast<uint64_t*>(ctx[i]->state), 24);
extra_hashes[ctx[i]->state[0] & 3](ctx[i]->state, 200, output + 32 * i);
}
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx)
{
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO>();
constexpr size_t MEM = xmrig::cn_select_memory<ALGO>();
if (VARIANT > 0 && size < 43) {
memset(output, 0, 32 * 4);
return;
}
for (size_t i = 0; i < 4; i++) {
keccak(input + size * i, static_cast<int>(size), ctx[i]->state, 200);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->state), reinterpret_cast<__m128i*>(ctx[i]->memory));
}
CONST_INIT(ctx[0], 0);
CONST_INIT(ctx[1], 1);
CONST_INIT(ctx[2], 2);
CONST_INIT(ctx[3], 3);
uint8_t* l0 = ctx[0]->memory;
uint8_t* l1 = ctx[1]->memory;
uint8_t* l2 = ctx[2]->memory;
uint8_t* l3 = ctx[3]->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx[0]->state);
uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx[1]->state);
uint64_t* h2 = reinterpret_cast<uint64_t*>(ctx[2]->state);
uint64_t* h3 = reinterpret_cast<uint64_t*>(ctx[3]->state);
__m128i ax0 = _mm_set_epi64x(h0[1] ^ h0[5], h0[0] ^ h0[4]);
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
__m128i ax1 = _mm_set_epi64x(h1[1] ^ h1[5], h1[0] ^ h1[4]);
__m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
__m128i ax2 = _mm_set_epi64x(h2[1] ^ h2[5], h2[0] ^ h2[4]);
__m128i bx2 = _mm_set_epi64x(h2[3] ^ h2[7], h2[2] ^ h2[6]);
__m128i ax3 = _mm_set_epi64x(h3[1] ^ h3[5], h3[0] ^ h3[4]);
__m128i bx3 = _mm_set_epi64x(h3[3] ^ h3[7], h3[2] ^ h3[6]);
__m128i cx0 = _mm_set_epi64x(0, 0);
__m128i cx1 = _mm_set_epi64x(0, 0);
__m128i cx2 = _mm_set_epi64x(0, 0);
__m128i cx3 = _mm_set_epi64x(0, 0);
uint64_t idx0, idx1, idx2, idx3;
idx0 = EXTRACT64(ax0);
idx1 = EXTRACT64(ax1);
idx2 = EXTRACT64(ax2);
idx3 = EXTRACT64(ax3);
for (size_t i = 0; i < ITERATIONS / 2; i++)
{
uint64_t hi, lo;
__m128i *ptr0, *ptr1, *ptr2, *ptr3;
// EVEN ROUND
CN_STEP1(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP1(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP1(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP1(ax3, bx3, cx3, l3, ptr3, idx3);
CN_STEP2(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP2(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP2(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP2(ax3, bx3, cx3, l3, ptr3, idx3);
CN_STEP3(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP3(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP3(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP3(ax3, bx3, cx3, l3, ptr3, idx3);
CN_STEP4(ax0, bx0, cx0, l0, mc0, ptr0, idx0);
CN_STEP4(ax1, bx1, cx1, l1, mc1, ptr1, idx1);
CN_STEP4(ax2, bx2, cx2, l2, mc2, ptr2, idx2);
CN_STEP4(ax3, bx3, cx3, l3, mc3, ptr3, idx3);
// ODD ROUND
CN_STEP1(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP1(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP1(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP1(ax3, cx3, bx3, l3, ptr3, idx3);
CN_STEP2(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP2(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP2(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP2(ax3, cx3, bx3, l3, ptr3, idx3);
CN_STEP3(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP3(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP3(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP3(ax3, cx3, bx3, l3, ptr3, idx3);
CN_STEP4(ax0, cx0, bx0, l0, mc0, ptr0, idx0);
CN_STEP4(ax1, cx1, bx1, l1, mc1, ptr1, idx1);
CN_STEP4(ax2, cx2, bx2, l2, mc2, ptr2, idx2);
CN_STEP4(ax3, cx3, bx3, l3, mc3, ptr3, idx3);
}
for (size_t i = 0; i < 4; i++) {
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->memory), reinterpret_cast<__m128i*>(ctx[i]->state));
keccakf(reinterpret_cast<uint64_t*>(ctx[i]->state), 24);
extra_hashes[ctx[i]->state[0] & 3](ctx[i]->state, 200, output + 32 * i);
}
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx)
{
}
constexpr size_t MASK = xmrig::cn_select_mask<ALGO>();
constexpr size_t ITERATIONS = xmrig::cn_select_iter<ALGO>();
constexpr size_t MEM = xmrig::cn_select_memory<ALGO>();
if (VARIANT > 0 && size < 43) {
memset(output, 0, 32 * 5);
return;
}
template<xmrig::Algo ALGO, bool SOFT_AES, int VARIANT>
inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
{
for (size_t i = 0; i < 5; i++) {
keccak(input + size * i, static_cast<int>(size), ctx[i]->state, 200);
cn_explode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->state), reinterpret_cast<__m128i*>(ctx[i]->memory));
}
CONST_INIT(ctx[0], 0);
CONST_INIT(ctx[1], 1);
CONST_INIT(ctx[2], 2);
CONST_INIT(ctx[3], 3);
CONST_INIT(ctx[4], 4);
uint8_t* l0 = ctx[0]->memory;
uint8_t* l1 = ctx[1]->memory;
uint8_t* l2 = ctx[2]->memory;
uint8_t* l3 = ctx[3]->memory;
uint8_t* l4 = ctx[4]->memory;
uint64_t* h0 = reinterpret_cast<uint64_t*>(ctx[0]->state);
uint64_t* h1 = reinterpret_cast<uint64_t*>(ctx[1]->state);
uint64_t* h2 = reinterpret_cast<uint64_t*>(ctx[2]->state);
uint64_t* h3 = reinterpret_cast<uint64_t*>(ctx[3]->state);
uint64_t* h4 = reinterpret_cast<uint64_t*>(ctx[4]->state);
__m128i ax0 = _mm_set_epi64x(h0[1] ^ h0[5], h0[0] ^ h0[4]);
__m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]);
__m128i ax1 = _mm_set_epi64x(h1[1] ^ h1[5], h1[0] ^ h1[4]);
__m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]);
__m128i ax2 = _mm_set_epi64x(h2[1] ^ h2[5], h2[0] ^ h2[4]);
__m128i bx2 = _mm_set_epi64x(h2[3] ^ h2[7], h2[2] ^ h2[6]);
__m128i ax3 = _mm_set_epi64x(h3[1] ^ h3[5], h3[0] ^ h3[4]);
__m128i bx3 = _mm_set_epi64x(h3[3] ^ h3[7], h3[2] ^ h3[6]);
__m128i ax4 = _mm_set_epi64x(h4[1] ^ h4[5], h4[0] ^ h4[4]);
__m128i bx4 = _mm_set_epi64x(h4[3] ^ h4[7], h4[2] ^ h4[6]);
__m128i cx0 = _mm_set_epi64x(0, 0);
__m128i cx1 = _mm_set_epi64x(0, 0);
__m128i cx2 = _mm_set_epi64x(0, 0);
__m128i cx3 = _mm_set_epi64x(0, 0);
__m128i cx4 = _mm_set_epi64x(0, 0);
uint64_t idx0, idx1, idx2, idx3, idx4;
idx0 = EXTRACT64(ax0);
idx1 = EXTRACT64(ax1);
idx2 = EXTRACT64(ax2);
idx3 = EXTRACT64(ax3);
idx4 = EXTRACT64(ax4);
for (size_t i = 0; i < ITERATIONS / 2; i++)
{
uint64_t hi, lo;
__m128i *ptr0, *ptr1, *ptr2, *ptr3, *ptr4;
// EVEN ROUND
CN_STEP1(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP1(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP1(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP1(ax3, bx3, cx3, l3, ptr3, idx3);
CN_STEP1(ax4, bx4, cx4, l4, ptr4, idx4);
CN_STEP2(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP2(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP2(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP2(ax3, bx3, cx3, l3, ptr3, idx3);
CN_STEP2(ax4, bx4, cx4, l4, ptr4, idx4);
CN_STEP3(ax0, bx0, cx0, l0, ptr0, idx0);
CN_STEP3(ax1, bx1, cx1, l1, ptr1, idx1);
CN_STEP3(ax2, bx2, cx2, l2, ptr2, idx2);
CN_STEP3(ax3, bx3, cx3, l3, ptr3, idx3);
CN_STEP3(ax4, bx4, cx4, l4, ptr4, idx4);
CN_STEP4(ax0, bx0, cx0, l0, mc0, ptr0, idx0);
CN_STEP4(ax1, bx1, cx1, l1, mc1, ptr1, idx1);
CN_STEP4(ax2, bx2, cx2, l2, mc2, ptr2, idx2);
CN_STEP4(ax3, bx3, cx3, l3, mc3, ptr3, idx3);
CN_STEP4(ax4, bx4, cx4, l4, mc4, ptr4, idx4);
// ODD ROUND
CN_STEP1(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP1(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP1(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP1(ax3, cx3, bx3, l3, ptr3, idx3);
CN_STEP1(ax4, cx4, bx4, l4, ptr4, idx4);
CN_STEP2(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP2(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP2(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP2(ax3, cx3, bx3, l3, ptr3, idx3);
CN_STEP2(ax4, cx4, bx4, l4, ptr4, idx4);
CN_STEP3(ax0, cx0, bx0, l0, ptr0, idx0);
CN_STEP3(ax1, cx1, bx1, l1, ptr1, idx1);
CN_STEP3(ax2, cx2, bx2, l2, ptr2, idx2);
CN_STEP3(ax3, cx3, bx3, l3, ptr3, idx3);
CN_STEP3(ax4, cx4, bx4, l4, ptr4, idx4);
CN_STEP4(ax0, cx0, bx0, l0, mc0, ptr0, idx0);
CN_STEP4(ax1, cx1, bx1, l1, mc1, ptr1, idx1);
CN_STEP4(ax2, cx2, bx2, l2, mc2, ptr2, idx2);
CN_STEP4(ax3, cx3, bx3, l3, mc3, ptr3, idx3);
CN_STEP4(ax4, cx4, bx4, l4, mc4, ptr4, idx4);
}
for (size_t i = 0; i < 5; i++) {
cn_implode_scratchpad<ALGO, MEM, SOFT_AES>(reinterpret_cast<__m128i*>(ctx[i]->memory), reinterpret_cast<__m128i*>(ctx[i]->state));
keccakf(reinterpret_cast<uint64_t*>(ctx[i]->state), 24);
extra_hashes[ctx[i]->state[0] & 3](ctx[i]->state, 200, output + 32 * i);
}
}
#endif /* __CRYPTONIGHT_X86_H__ */

View File

@@ -105,6 +105,23 @@ static inline __m128i soft_aesenc(const uint32_t* in, __m128i key)
return _mm_xor_si128(out, key);
}
static inline __m128i soft_aesenc(__m128i in, __m128i key)
{
uint32_t x0, x1, x2, x3;
x0 = _mm_cvtsi128_si32(in);
x1 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0x55));
x2 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0xAA));
x3 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0xFF));
__m128i out = _mm_set_epi32(
(saes_table[0][x3 & 0xff] ^ saes_table[1][(x0 >> 8) & 0xff] ^ saes_table[2][(x1 >> 16) & 0xff] ^ saes_table[3][x2 >> 24]),
(saes_table[0][x2 & 0xff] ^ saes_table[1][(x3 >> 8) & 0xff] ^ saes_table[2][(x0 >> 16) & 0xff] ^ saes_table[3][x1 >> 24]),
(saes_table[0][x1 & 0xff] ^ saes_table[1][(x2 >> 8) & 0xff] ^ saes_table[2][(x3 >> 16) & 0xff] ^ saes_table[3][x0 >> 24]),
(saes_table[0][x0 & 0xff] ^ saes_table[1][(x1 >> 8) & 0xff] ^ saes_table[2][(x2 >> 16) & 0xff] ^ saes_table[3][x3 >> 24]));
return _mm_xor_si128(out, key);
}
static inline uint32_t sub_word(uint32_t key)
{
return (saes_sbox[key >> 24 ] << 24) |

View File

@@ -29,9 +29,14 @@
* Dev donation.
*
* Percentage of your hashing power that you want to donate to the developer, can be 0 if you don't want to do that.
* Example of how it works for the default setting of 1:
* You miner will mine into your usual pool for 99 minutes, then switch to the developer's pool for 1 minute.
* Since v2.5.1 start time randomized in range from 50 to 150 minutes minus donation time.
*
* Example of how it works for the setting of 1%:
* You miner will mine into your usual pool for random time (in range from 49.5 to 148.5 minutes),
* then switch to the developer's pool for 1 minute, then switch again to your pool for 99 minutes
* and then switch agaiin to developer's pool for 1 minute, these rounds will continue until miner working.
*
* Randomised only first round, to prevent waves on the donation pool.
*
* Switching is instant, and only happens after a successful connection, so you never loose any hashes.
*
* If you plan on changing this setting to 0 please consider making a one off donation to my wallet:
@@ -39,7 +44,7 @@
* BTC: 1P7ujsXeX7GxQwHNnJsRMgAdNkFZmNVqJT
*/
constexpr const int kDefaultDonateLevel = 5;
constexpr const int kMinDonateLevel = 1;
constexpr const int kMinimumDonateLevel = 1;
#endif /* __DONATE_H__ */

View File

@@ -74,6 +74,7 @@ public:
MaxCPUUsageKey = 1004,
SafeKey = 1005,
ThreadsKey = 't',
HardwareAESKey = 1011,
// xmrig-proxy
AccessLogFileKey = 'A',

View File

@@ -27,8 +27,8 @@
#include <stdint.h>
#include "common/xmrig.h"
#include "rapidjson/fwd.h"
#include "xmrig.h"
namespace xmrig {
@@ -43,14 +43,23 @@ public:
CUDA
};
enum Multiway {
SingleWay = 1,
DoubleWay,
TripleWay,
QuadWay,
PentaWay
};
virtual ~IThread() {}
virtual Algo algorithm() const = 0;
virtual int multiway() const = 0;
virtual int priority() const = 0;
virtual int64_t affinity() const = 0;
virtual size_t index() const = 0;
virtual Type type() const = 0;
virtual Algo algorithm() const = 0;
virtual int priority() const = 0;
virtual int64_t affinity() const = 0;
virtual Multiway multiway() const = 0;
virtual rapidjson::Value toConfig(rapidjson::Document &doc) const = 0;
virtual size_t index() const = 0;
virtual Type type() const = 0;
# ifndef XMRIG_NO_API
virtual rapidjson::Value toAPI(rapidjson::Document &doc) const = 0;

View File

@@ -33,10 +33,11 @@ class IWorker
public:
virtual ~IWorker() {}
virtual bool start() = 0;
virtual bool selfTest() = 0;
virtual size_t id() const = 0;
virtual uint64_t hashCount() const = 0;
virtual uint64_t timestamp() const = 0;
virtual void start() = 0;
};

View File

@@ -4,8 +4,8 @@
* 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>
*
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 XMRig <https://github.com/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
@@ -38,6 +38,8 @@ Log *Log::m_self = nullptr;
void Log::message(Log::Level level, const char* fmt, ...)
{
uv_mutex_lock(&m_mutex);
va_list args;
va_list copy;
va_start(args, fmt);
@@ -47,11 +49,15 @@ void Log::message(Log::Level level, const char* fmt, ...)
backend->message(level, fmt, copy);
va_end(copy);
}
uv_mutex_unlock(&m_mutex);
}
void Log::text(const char* fmt, ...)
{
uv_mutex_lock(&m_mutex);
va_list args;
va_list copy;
va_start(args, fmt);
@@ -63,6 +69,8 @@ void Log::text(const char* fmt, ...)
}
va_end(args);
uv_mutex_unlock(&m_mutex);
}

View File

@@ -4,8 +4,8 @@
* 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>
*
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 XMRig <https://github.com/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
@@ -25,6 +25,7 @@
#define __LOG_H__
#include <assert.h>
#include <uv.h>
#include <vector>
@@ -54,20 +55,28 @@ public:
constexpr static const char* kCL_GRAY = "\x1B[90m";
# endif
static inline Log* i() { return m_self; }
static inline Log* i() { assert(m_self != nullptr); return m_self; }
static inline void add(ILogBackend *backend) { i()->m_backends.push_back(backend); }
static inline void init() { if (!m_self) { m_self = new Log();} }
static inline void release() { delete m_self; }
static inline void init() { if (!m_self) { new Log(); } }
static inline void release() { assert(m_self != nullptr); delete m_self; }
void message(Level level, const char* fmt, ...);
void text(const char* fmt, ...);
private:
inline Log() {}
inline Log() {
assert(m_self == nullptr);
uv_mutex_init(&m_mutex);
m_self = this;
}
~Log();
static Log *m_self;
std::vector<ILogBackend*> m_backends;
uv_mutex_t m_mutex;
};

View File

@@ -32,7 +32,6 @@
#include "interfaces/IClientListener.h"
#include "log/Log.h"
#include "net/Client.h"
#include "net/Url.h"
#include "rapidjson/document.h"
#include "rapidjson/error/en.h"
#include "rapidjson/stringbuffer.h"
@@ -97,7 +96,7 @@ Client::~Client()
void Client::connect()
{
resolve(m_url.host());
resolve(m_pool.host());
}
@@ -106,10 +105,10 @@ void Client::connect()
*
* @param url
*/
void Client::connect(const Url *url)
void Client::connect(const Pool &url)
{
setUrl(url);
resolve(m_url.host());
setPool(url);
connect();
}
@@ -121,24 +120,19 @@ void Client::deleteLater()
m_listener = nullptr;
if (state() == HostLookupState) {
uv_cancel(reinterpret_cast<uv_req_t*>(&m_resolver));
return;
}
if (!disconnect() && m_state != ClosingState) {
if (!disconnect()) {
m_storage.remove(m_key);
}
}
void Client::setUrl(const Url *url)
void Client::setPool(const Pool &pool)
{
if (!url || !url->isValid()) {
if (!pool.isValid()) {
return;
}
m_url = url;
m_pool = pool;
}
@@ -146,7 +140,7 @@ void Client::tick(uint64_t now)
{
if (m_state == ConnectedState) {
if (m_expire && now > m_expire) {
LOG_DEBUG_ERR("[%s:%u] timeout", m_url.host(), m_url.port());
LOG_DEBUG_ERR("[%s] timeout", m_pool.url());
close();
}
else if (m_keepAlive && now > m_keepAlive) {
@@ -207,28 +201,7 @@ bool Client::close()
setState(ClosingState);
uv_stream_t *stream = reinterpret_cast<uv_stream_t*>(m_socket);
if (uv_is_readable(stream) == 1) {
uv_read_stop(stream);
}
if (uv_is_writable(stream) == 1) {
const int rc = uv_shutdown(new uv_shutdown_t, stream, [](uv_shutdown_t* req, int status) {
if (uv_is_closing(reinterpret_cast<uv_handle_t*>(req->handle)) == 0) {
uv_close(reinterpret_cast<uv_handle_t*>(req->handle), Client::onClose);
}
delete req;
});
assert(rc == 0);
if (rc != 0) {
onClose();
}
}
else {
if (uv_is_closing(reinterpret_cast<uv_handle_t*>(m_socket)) == 0) {
uv_close(reinterpret_cast<uv_handle_t*>(m_socket), Client::onClose);
}
@@ -266,11 +239,10 @@ bool Client::parseJob(const rapidjson::Value &params, int *code)
}
# ifdef XMRIG_PROXY_PROJECT
Job job(m_id, m_url.variant());
Job job(m_id, m_pool.variant());
job.setClientId(m_rpcId);
job.setCoin(m_url.coin());
# else
Job job(m_id, m_nicehash, m_url.algo(), m_url.variant());
Job job(m_id, m_nicehash, m_pool.algo(), m_pool.variant());
# endif
if (!job.setId(params["job_id"].GetString())) {
@@ -307,7 +279,7 @@ bool Client::parseJob(const rapidjson::Value &params, int *code)
}
if (!m_quiet) {
LOG_WARN("[%s:%u] duplicate job received, reconnect", m_url.host(), m_url.port());
LOG_WARN("[%s] duplicate job received, reconnect", m_pool.url());
}
close();
@@ -323,7 +295,7 @@ bool Client::parseLogin(const rapidjson::Value &result, int *code)
}
# ifndef XMRIG_PROXY_PROJECT
m_nicehash = m_url.isNicehash();
m_nicehash = m_pool.isNicehash();
# endif
if (result.HasMember("extensions")) {
@@ -351,7 +323,7 @@ int Client::resolve(const char *host)
const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host, nullptr, &m_hints);
if (r) {
if (!m_quiet) {
LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host, m_url.port(), uv_strerror(r));
LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host, m_pool.port(), uv_strerror(r));
}
return 1;
}
@@ -362,9 +334,9 @@ int Client::resolve(const char *host)
int64_t Client::send(size_t size)
{
LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size, m_sendBuf);
LOG_DEBUG("[%s] send (%d bytes): \"%s\"", m_pool.url(), size, m_sendBuf);
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);
LOG_DEBUG_ERR("[%s] send failed, invalid state: %d", m_pool.url(), m_state);
return -1;
}
@@ -402,7 +374,7 @@ void Client::connect(sockaddr *addr)
{
setState(ConnectingState);
reinterpret_cast<struct sockaddr_in*>(addr)->sin_port = htons(m_url.port());
reinterpret_cast<sockaddr_in*>(addr)->sin_port = htons(m_pool.port());
delete m_socket;
uv_connect_t *req = new uv_connect_t;
@@ -436,9 +408,9 @@ void Client::login()
doc.AddMember("method", "login", allocator);
rapidjson::Value params(rapidjson::kObjectType);
params.AddMember("login", rapidjson::StringRef(m_url.user()), allocator);
params.AddMember("pass", rapidjson::StringRef(m_url.password()), allocator);
params.AddMember("agent", rapidjson::StringRef(m_agent), allocator);
params.AddMember("login", rapidjson::StringRef(m_pool.user()), allocator);
params.AddMember("pass", rapidjson::StringRef(m_pool.password()), allocator);
params.AddMember("agent", rapidjson::StringRef(m_agent), allocator);
doc.AddMember("params", params, allocator);
@@ -477,11 +449,11 @@ void Client::parse(char *line, size_t len)
line[len - 1] = '\0';
LOG_DEBUG("[%s:%u] received (%d bytes): \"%s\"", m_url.host(), m_url.port(), len, line);
LOG_DEBUG("[%s] received (%d bytes): \"%s\"", m_pool.url(), len, line);
if (len < 32 || line[0] != '{') {
if (!m_quiet) {
LOG_ERR("[%s:%u] JSON decode failed", m_url.host(), m_url.port());
LOG_ERR("[%s] JSON decode failed", m_pool.url());
}
return;
@@ -490,7 +462,7 @@ void Client::parse(char *line, size_t len)
rapidjson::Document doc;
if (doc.ParseInsitu(line).HasParseError()) {
if (!m_quiet) {
LOG_ERR("[%s:%u] JSON decode failed: \"%s\"", m_url.host(), m_url.port(), rapidjson::GetParseError_En(doc.GetParseError()));
LOG_ERR("[%s] JSON decode failed: \"%s\"", m_pool.url(), rapidjson::GetParseError_En(doc.GetParseError()));
}
return;
@@ -532,7 +504,7 @@ void Client::parseNotification(const char *method, const rapidjson::Value &param
{
if (error.IsObject()) {
if (!m_quiet) {
LOG_ERR("[%s:%u] error: \"%s\", code: %d", m_url.host(), m_url.port(), error["message"].GetString(), error["code"].GetInt());
LOG_ERR("[%s] error: \"%s\", code: %d", m_pool.url(), error["message"].GetString(), error["code"].GetInt());
}
return;
}
@@ -550,7 +522,7 @@ void Client::parseNotification(const char *method, const rapidjson::Value &param
return;
}
LOG_WARN("[%s:%u] unsupported method: \"%s\"", m_url.host(), m_url.port(), method);
LOG_WARN("[%s] unsupported method: \"%s\"", m_pool.url(), method);
}
@@ -566,7 +538,7 @@ void Client::parseResponse(int64_t id, const rapidjson::Value &result, const rap
m_results.erase(it);
}
else if (!m_quiet) {
LOG_ERR("[%s:%u] error: \"%s\", code: %d", m_url.host(), m_url.port(), message, error["code"].GetInt());
LOG_ERR("[%s] error: \"%s\", code: %d", m_pool.url(), message, error["code"].GetInt());
}
if (isCriticalError(message)) {
@@ -584,7 +556,7 @@ void Client::parseResponse(int64_t id, const rapidjson::Value &result, const rap
int code = -1;
if (!parseLogin(result, &code)) {
if (!m_quiet) {
LOG_ERR("[%s:%u] login error code: %d", m_url.host(), m_url.port(), code);
LOG_ERR("[%s] login error code: %d", m_pool.url(), code);
}
close();
@@ -636,7 +608,7 @@ void Client::reconnect()
void Client::setState(SocketState state)
{
LOG_DEBUG("[%s:%u] state: %d", m_url.host(), m_url.port(), state);
LOG_DEBUG("[%s] state: %d", m_pool.url(), state);
if (m_state == state) {
return;
@@ -650,8 +622,8 @@ void Client::startTimeout()
{
m_expire = 0;
if (m_url.keepAlive()) {
m_keepAlive = uv_now(uv_default_loop()) + (m_url.keepAlive() * 1000);
if (m_pool.keepAlive()) {
m_keepAlive = uv_now(uv_default_loop()) + (m_pool.keepAlive() * 1000);
}
}
@@ -689,7 +661,7 @@ void Client::onConnect(uv_connect_t *req, int status)
if (status < 0) {
if (!client->m_quiet) {
LOG_ERR("[%s:%u] connect error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status));
LOG_ERR("[%s] connect error: \"%s\"", client->m_pool.url(), uv_strerror(status));
}
delete req;
@@ -717,7 +689,7 @@ void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
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((int) nread));
LOG_ERR("[%s] read error: \"%s\"", client->m_pool.url(), uv_strerror((int) nread));
}
client->close();
@@ -777,7 +749,7 @@ void Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res)
if (status < 0) {
if (!client->m_quiet) {
LOG_ERR("[%s:%u] DNS error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status));
LOG_ERR("[%s] DNS error: \"%s\"", client->m_pool.url(), uv_strerror(status));
}
return client->reconnect();
@@ -801,7 +773,7 @@ void Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res)
if (ipv4.empty() && ipv6.empty()) {
if (!client->m_quiet) {
LOG_ERR("[%s:%u] DNS error: \"No IPv4 (A) or IPv6 (AAAA) records found\"", client->m_url.host(), client->m_url.port());
LOG_ERR("[%s] DNS error: \"No IPv4 (A) or IPv6 (AAAA) records found\"", client->m_pool.url());
}
uv_freeaddrinfo(res);

View File

@@ -34,7 +34,7 @@
#include "net/Job.h"
#include "net/Storage.h"
#include "net/SubmitResult.h"
#include "net/Url.h"
#include "net/Pool.h"
#include "rapidjson/fwd.h"
@@ -61,18 +61,18 @@ public:
bool disconnect();
int64_t submit(const JobResult &result);
void connect();
void connect(const Url *url);
void connect(const Pool &pool);
void deleteLater();
void setUrl(const Url *url);
void setPool(const Pool &pool);
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(); }
inline const char *host() const { return m_pool.host(); }
inline const char *ip() const { return m_ip; }
inline const Job &job() const { return m_job; }
inline int id() const { return m_id; }
inline SocketState state() const { return m_state; }
inline uint16_t port() const { return m_url.port(); }
inline uint16_t port() const { return m_pool.port(); }
inline void setQuiet(bool quiet) { m_quiet = quiet; }
inline void setRetryPause(int ms) { m_retryPause = ms; }
@@ -117,6 +117,7 @@ private:
int m_retryPause;
int64_t m_failures;
Job m_job;
Pool m_pool;
size_t m_recvBufPos;
SocketState m_state;
std::map<int64_t, SubmitResult> m_results;
@@ -124,7 +125,6 @@ private:
uint64_t m_jobs;
uint64_t m_keepAlive;
uintptr_t m_key;
Url m_url;
uv_buf_t m_recvBuf;
uv_getaddrinfo_t m_resolver;
uv_stream_t *m_stream;

View File

@@ -209,6 +209,17 @@ void Job::toHex(const unsigned char* in, unsigned int len, char* out)
}
#ifdef APP_DEBUG
char *Job::toHex(const unsigned char* in, unsigned int len)
{
char *out = new char[len * 2 + 1]();
toHex(in, len, out);
return out;
}
#endif
bool Job::operator==(const Job &other) const
{
return m_id == other.m_id && memcmp(m_blob, other.m_blob, sizeof(m_blob)) == 0;

View File

@@ -30,8 +30,8 @@
#include <stdint.h>
#include "common/xmrig.h"
#include "net/Id.h"
#include "xmrig.h"
class Job
@@ -69,6 +69,10 @@ public:
static inline uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; }
static void toHex(const unsigned char* in, unsigned int len, char* out);
# ifdef APP_DEBUG
static char *toHex(const unsigned char* in, unsigned int len);
# endif
bool operator==(const Job &other) const;
bool operator!=(const Job &other) const;

View File

@@ -38,7 +38,6 @@
#include "net/strategies/FailoverStrategy.h"
#include "net/strategies/SinglePoolStrategy.h"
#include "net/SubmitResult.h"
#include "net/Url.h"
#include "workers/Workers.h"
#include "core/Controller.h"
#include "core/Config.h"
@@ -52,7 +51,7 @@ Network::Network(xmrig::Controller *controller) :
Workers::setListener(this);
const std::vector<Url*> &pools = controller->config()->pools();
const std::vector<Pool> &pools = controller->config()->pools();
if (pools.size() > 1) {
m_strategy = new FailoverStrategy(pools, controller->config()->retryPause(), controller->config()->retries(), this);
@@ -62,7 +61,7 @@ Network::Network(xmrig::Controller *controller) :
}
if (controller->config()->donateLevel() > 0) {
m_donate = new DonateStrategy(controller->config()->donateLevel(), controller->config()->pools().front()->user(), controller->config()->algorithm(), this);
m_donate = new DonateStrategy(controller->config()->donateLevel(), controller->config()->pools().front().user(), controller->config()->algorithm(), this);
}
m_timer.data = this;

280
src/net/Pool.cpp Normal file
View File

@@ -0,0 +1,280 @@
/* 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 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 XMRig <https://github.com/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 <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "net/Pool.h"
#ifdef _MSC_VER
# define strncasecmp _strnicmp
# define strcasecmp _stricmp
#endif
static const char *algoNames[] = {
"cryptonight",
# ifndef XMRIG_NO_AEON
"cryptonight-lite",
# else
nullptr,
# endif
# ifndef XMRIG_NO_SUMO
"cryptonight-heavy"
# else
nullptr
# endif
};
static const char *algoNamesShort[] = {
"cn",
# ifndef XMRIG_NO_AEON
"cn-lite",
# else
nullptr,
# endif
# ifndef XMRIG_NO_SUMO
"cn-heavy"
# else
nullptr
# endif
};
Pool::Pool() :
m_nicehash(false),
m_keepAlive(0),
m_port(kDefaultPort),
m_algo(xmrig::CRYPTONIGHT),
m_variant(xmrig::VARIANT_AUTO)
{
}
/**
* @brief Parse url.
*
* Valid urls:
* example.com
* example.com:3333
* stratum+tcp://example.com
* stratum+tcp://example.com:3333
*
* @param url
*/
Pool::Pool(const char *url) :
m_nicehash(false),
m_keepAlive(0),
m_port(kDefaultPort),
m_algo(xmrig::CRYPTONIGHT),
m_variant(xmrig::VARIANT_AUTO)
{
parse(url);
}
Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, xmrig::Variant variant) :
m_nicehash(nicehash),
m_keepAlive(keepAlive),
m_port(port),
m_algo(xmrig::CRYPTONIGHT),
m_host(host),
m_password(password),
m_user(user),
m_variant(variant)
{
const size_t size = m_host.size() + 8;
assert(size > 8);
char *url = new char[size]();
snprintf(url, size - 1, "%s:%d", m_host.data(), m_port);
m_url = url;
}
const char *Pool::algoName(xmrig::Algo algorithm)
{
return algoNames[algorithm];
}
xmrig::Algo Pool::algorithm(const char *algo)
{
# ifndef XMRIG_NO_AEON
if (strcasecmp(algo, "cryptonight-light") == 0) {
fprintf(stderr, "Algorithm \"cryptonight-light\" is deprecated, use \"cryptonight-lite\" instead\n");
return xmrig::CRYPTONIGHT_LITE;
}
# endif
const size_t size = sizeof(algoNames) / sizeof(algoNames[0]);
assert(size == (sizeof(algoNamesShort) / sizeof(algoNamesShort[0])));
for (size_t i = 0; i < size; i++) {
if ((algoNames[i] && strcasecmp(algo, algoNames[i]) == 0) || (algoNamesShort[i] && strcasecmp(algo, algoNamesShort[i]) == 0)) {
return static_cast<xmrig::Algo>(i);
}
}
fprintf(stderr, "Unknown algorithm \"%s\" specified.\n", algo);
return xmrig::INVALID_ALGO;
}
bool Pool::parse(const char *url)
{
assert(url != nullptr);
const char *p = strstr(url, "://");
const char *base = url;
if (p) {
if (strncasecmp(url, "stratum+tcp://", 14)) {
return false;
}
base = url + 14;
}
if (!strlen(base) || *base == '/') {
return false;
}
m_url = url;
if (base[0] == '[') {
return parseIPv6(base);
}
const char *port = strchr(base, ':');
if (!port) {
m_host = base;
return true;
}
const size_t size = port++ - base + 1;
char *host = new char[size]();
memcpy(host, base, size - 1);
m_host = host;
m_port = static_cast<uint16_t>(strtol(port, nullptr, 10));
return true;
}
bool Pool::setUserpass(const char *userpass)
{
const char *p = strchr(userpass, ':');
if (!p) {
return false;
}
char *user = new char[p - userpass + 1]();
strncpy(user, userpass, p - userpass);
m_user = user;
m_password = p + 1;
return true;
}
void Pool::adjust(xmrig::Algo algo)
{
if (!isValid()) {
return;
}
m_algo = algo;
if (strstr(m_host.data(), ".nicehash.com")) {
m_keepAlive = false;
m_nicehash = true;
}
if (strstr(m_host.data(), ".minergate.com")) {
m_keepAlive = false;
}
}
void Pool::setVariant(int variant)
{
switch (variant) {
case xmrig::VARIANT_AUTO:
case xmrig::VARIANT_NONE:
case xmrig::VARIANT_V1:
m_variant = static_cast<xmrig::Variant>(variant);
break;
default:
assert(false);
break;
}
}
bool Pool::isEqual(const Pool &other) const
{
return (m_nicehash == other.m_nicehash
&& m_keepAlive == other.m_keepAlive
&& m_port == other.m_port
&& m_algo == other.m_algo
&& m_host == other.m_host
&& m_password == other.m_password
&& m_url == other.m_url
&& m_user == other.m_user
&& m_variant == other.m_variant);
}
bool Pool::parseIPv6(const char *addr)
{
const char *end = strchr(addr, ']');
if (!end) {
return false;
}
const char *port = strchr(end, ':');
if (!port) {
return false;
}
const size_t size = end - addr;
char *host = new char[size]();
memcpy(host, addr + 1, size - 1);
m_host = host;
m_port = static_cast<uint16_t>(strtol(port + 1, nullptr, 10));
return true;
}

96
src/net/Pool.h Normal file
View File

@@ -0,0 +1,96 @@
/* 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 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 XMRig <https://github.com/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 __POOL_H__
#define __POOL_H__
#include <stdint.h>
#include "common/utils/c_str.h"
#include "common/xmrig.h"
class Pool
{
public:
constexpr static const char *kDefaultPassword = "x";
constexpr static const char *kDefaultUser = "x";
constexpr static uint16_t kDefaultPort = 3333;
constexpr static int kKeepAliveTimeout = 60;
Pool();
Pool(const char *url);
Pool(const char *host,
uint16_t port,
const char *user = nullptr,
const char *password = nullptr,
int keepAlive = 0,
bool nicehash = false,
xmrig::Variant variant = xmrig::VARIANT_AUTO
);
static const char *algoName(xmrig::Algo algorithm);
static xmrig::Algo algorithm(const char *algo);
inline bool isNicehash() const { return m_nicehash; }
inline bool isValid() const { return !m_host.isNull() && m_port > 0; }
inline const char *host() const { return m_host.data(); }
inline const char *password() const { return !m_password.isNull() ? m_password.data() : kDefaultPassword; }
inline const char *url() const { return m_url.data(); }
inline const char *user() const { return !m_user.isNull() ? m_user.data() : kDefaultUser; }
inline int keepAlive() const { return m_keepAlive; }
inline uint16_t port() const { return m_port; }
inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; }
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
inline void setPassword(const char *password) { m_password = password; }
inline void setUser(const char *user) { m_user = user; }
inline xmrig::Algo algo() const { return m_algo; }
inline xmrig::Variant variant() const { return m_variant; }
inline bool operator!=(const Pool &other) const { return !isEqual(other); }
inline bool operator==(const Pool &other) const { return isEqual(other); }
bool parse(const char *url);
bool setUserpass(const char *userpass);
void adjust(xmrig::Algo algo);
void setVariant(int variant);
bool isEqual(const Pool &other) const;
private:
bool parseIPv6(const char *addr);
bool m_nicehash;
int m_keepAlive;
uint16_t m_port;
xmrig::Algo m_algo;
xmrig::c_str m_host;
xmrig::c_str m_password;
xmrig::c_str m_url;
xmrig::c_str m_user;
xmrig::Variant m_variant;
};
#endif /* __POOL_H__ */

View File

@@ -1,284 +0,0 @@
/* 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 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 XMRig <https://github.com/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 <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "net/Url.h"
#include "xmrig.h"
#ifdef _MSC_VER
# define strncasecmp(x,y,z) _strnicmp(x,y,z)
#endif
Url::Url() :
m_nicehash(false),
m_host(nullptr),
m_password(nullptr),
m_user(nullptr),
m_algo(xmrig::CRYPTONIGHT),
m_keepAlive(0),
m_variant(xmrig::VARIANT_AUTO),
m_url(nullptr),
m_port(kDefaultPort)
{
}
/**
* @brief Parse url.
*
* Valid urls:
* example.com
* example.com:3333
* stratum+tcp://example.com
* stratum+tcp://example.com:3333
*
* @param url
*/
Url::Url(const char *url) :
m_nicehash(false),
m_host(nullptr),
m_password(nullptr),
m_user(nullptr),
m_algo(xmrig::CRYPTONIGHT),
m_keepAlive(0),
m_variant(xmrig::VARIANT_AUTO),
m_url(nullptr),
m_port(kDefaultPort)
{
parse(url);
}
Url::Url(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, int variant) :
m_nicehash(nicehash),
m_password(password ? strdup(password) : nullptr),
m_user(user ? strdup(user) : nullptr),
m_algo(xmrig::CRYPTONIGHT),
m_keepAlive(keepAlive),
m_variant(variant),
m_url(nullptr),
m_port(port)
{
m_host = strdup(host);
}
Url::~Url()
{
free(m_host);
free(m_password);
free(m_user);
if (m_url) {
delete [] m_url;
}
}
bool Url::parse(const char *url)
{
const char *p = strstr(url, "://");
const char *base = url;
if (p) {
if (strncasecmp(url, "stratum+tcp://", 14)) {
return false;
}
base = url + 14;
}
if (!strlen(base) || *base == '/') {
return false;
}
if (base[0] == '[') {
return parseIPv6(base);
}
const char *port = strchr(base, ':');
if (!port) {
m_host = strdup(base);
return false;
}
const size_t size = port++ - base + 1;
m_host = new char[size]();
memcpy(m_host, base, size - 1);
m_port = (uint16_t) strtol(port, nullptr, 10);
return true;
}
bool Url::setUserpass(const char *userpass)
{
const char *p = strchr(userpass, ':');
if (!p) {
return false;
}
free(m_user);
free(m_password);
m_user = static_cast<char*>(calloc(p - userpass + 1, 1));
strncpy(m_user, userpass, p - userpass);
m_password = strdup(p + 1);
return true;
}
const char *Url::url() const
{
if (!m_url) {
const size_t size = strlen(m_host) + 8;
m_url = new char[size];
snprintf(m_url, size - 1, "%s:%d", m_host, m_port);
}
return m_url;
}
void Url::adjust(int algo)
{
if (!isValid()) {
return;
}
m_algo = algo;
if (strstr(m_host, ".nicehash.com")) {
m_keepAlive = false;
m_nicehash = true;
}
if (strstr(m_host, ".minergate.com")) {
m_keepAlive = false;
}
}
void Url::setPassword(const char *password)
{
if (!password) {
return;
}
free(m_password);
m_password = strdup(password);
}
void Url::setUser(const char *user)
{
if (!user) {
return;
}
free(m_user);
m_user = strdup(user);
}
void Url::setVariant(int variant)
{
switch (variant) {
case xmrig::VARIANT_AUTO:
case xmrig::VARIANT_NONE:
case xmrig::VARIANT_V1:
m_variant = variant;
break;
default:
break;
}
}
bool Url::operator==(const Url &other) const
{
if (m_port != other.m_port || m_keepAlive != other.m_keepAlive || m_nicehash != other.m_nicehash) {
return false;
}
if (strcmp(host(), other.host()) != 0 || strcmp(user(), other.user()) != 0 || strcmp(password(), other.password()) != 0) {
return false;
}
return true;
}
Url &Url::operator=(const Url *other)
{
m_keepAlive = other->m_keepAlive;
m_algo = other->m_algo;
m_variant = other->m_variant;
m_nicehash = other->m_nicehash;
m_port = other->m_port;
free(m_host);
m_host = strdup(other->m_host);
setPassword(other->m_password);
setUser(other->m_user);
if (m_url) {
delete [] m_url;
m_url = nullptr;
}
return *this;
}
bool Url::parseIPv6(const char *addr)
{
const char *end = strchr(addr, ']');
if (!end) {
return false;
}
const char *port = strchr(end, ':');
if (!port) {
return false;
}
const size_t size = end - addr;
m_host = new char[size]();
memcpy(m_host, addr + 1, size - 1);
m_port = (uint16_t) strtol(port + 1, nullptr, 10);
return true;
}

View File

@@ -1,82 +0,0 @@
/* 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 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 XMRig <https://github.com/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 __URL_H__
#define __URL_H__
#include <stdint.h>
class Url
{
public:
constexpr static const char *kDefaultPassword = "x";
constexpr static const char *kDefaultUser = "x";
constexpr static uint16_t kDefaultPort = 3333;
constexpr static int kKeepAliveTimeout = 60;
Url();
Url(const char *url);
Url(const char *host, uint16_t port, const char *user = nullptr, const char *password = nullptr, int keepAlive = 0, bool nicehash = false, int variant = -1);
~Url();
inline bool isNicehash() const { return m_nicehash; }
inline bool isValid() const { return m_host && m_port > 0; }
inline const char *host() const { return m_host; }
inline const char *password() const { return m_password ? m_password : kDefaultPassword; }
inline const char *user() const { return m_user ? m_user : kDefaultUser; }
inline int algo() const { return m_algo; }
inline int keepAlive() const { return m_keepAlive; }
inline int variant() const { return m_variant; }
inline uint16_t port() const { return m_port; }
inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; }
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
inline void setVariant(bool monero) { m_variant = monero; }
bool parse(const char *url);
bool setUserpass(const char *userpass);
const char *url() const;
void adjust(int algo);
void setPassword(const char *password);
void setUser(const char *user);
void setVariant(int variant);
bool operator==(const Url &other) const;
Url &operator=(const Url *other);
private:
bool parseIPv6(const char *addr);
bool m_nicehash;
char *m_host;
char *m_password;
char *m_user;
int m_algo;
int m_keepAlive;
int m_variant;
mutable char *m_url;
uint16_t m_port;
};
#endif /* __URL_H__ */

View File

@@ -22,13 +22,13 @@
*/
#include "common/Platform.h"
#include "common/xmrig.h"
#include "interfaces/IStrategyListener.h"
#include "net/Client.h"
#include "net/Job.h"
#include "net/strategies/DonateStrategy.h"
#include "net/strategies/FailoverStrategy.h"
#include "Platform.h"
#include "xmrig.h"
extern "C"
@@ -41,8 +41,8 @@ const static char *kDonatePool1 = "miner.fee.xmrig.com";
const static char *kDonatePool2 = "emergency.fee.xmrig.com";
static inline int random(int min, int max){
return min + rand() / (RAND_MAX / (max - min + 1) + 1);
static inline float randomf(float min, float max) {
return (max - min) * ((((float) rand()) / (float) RAND_MAX)) + min;
}
@@ -60,17 +60,17 @@ DonateStrategy::DonateStrategy(int level, const char *user, int algo, IStrategyL
Job::toHex(hash, 32, userId);
if (algo == xmrig::CRYPTONIGHT) {
m_pools.push_back(new Url(kDonatePool1, 6666, userId, nullptr, false, true));
m_pools.push_back(new Url(kDonatePool1, 80, userId, nullptr, false, true));
m_pools.push_back(new Url(kDonatePool2, 5555, "48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD", "emergency", false, false));
m_pools.push_back(Pool(kDonatePool1, 6666, userId, nullptr, false, true));
m_pools.push_back(Pool(kDonatePool1, 80, userId, nullptr, false, true));
m_pools.push_back(Pool(kDonatePool2, 5555, "48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD", "emergency", false, false));
}
else if (algo == xmrig::CRYPTONIGHT_HEAVY) {
m_pools.push_back(new Url(kDonatePool1, 8888, userId, nullptr, false, true));
m_pools.push_back(new Url(kDonatePool1, 8889, userId, nullptr, false, true));
m_pools.push_back(Pool(kDonatePool1, 8888, userId, nullptr, false, true));
m_pools.push_back(Pool(kDonatePool1, 8889, userId, nullptr, false, true));
}
else {
m_pools.push_back(new Url(kDonatePool1, 5555, userId, nullptr, false, true));
m_pools.push_back(new Url(kDonatePool1, 7777, userId, nullptr, false, true));
m_pools.push_back(Pool(kDonatePool1, 5555, userId, nullptr, false, true));
m_pools.push_back(Pool(kDonatePool1, 7777, userId, nullptr, false, true));
}
m_strategy = new FailoverStrategy(m_pools, 1, 1, this, true);
@@ -78,7 +78,7 @@ DonateStrategy::DonateStrategy(int level, const char *user, int algo, IStrategyL
m_timer.data = this;
uv_timer_init(uv_default_loop(), &m_timer);
idle(random(3000, 9000) * 1000 - m_donateTime);
idle(m_idleTime * randomf(0.5, 1.5));
}

View File

@@ -32,6 +32,7 @@
#include "interfaces/IClientListener.h"
#include "interfaces/IStrategy.h"
#include "interfaces/IStrategyListener.h"
#include "net/Pool.h"
class Client;
@@ -71,7 +72,7 @@ private:
const int m_idleTime;
IStrategy *m_strategy;
IStrategyListener *m_listener;
std::vector<Url*> m_pools;
std::vector<Pool> m_pools;
uv_timer_t m_timer;
};

View File

@@ -22,13 +22,13 @@
*/
#include "common/Platform.h"
#include "interfaces/IStrategyListener.h"
#include "net/Client.h"
#include "net/strategies/FailoverStrategy.h"
#include "Platform.h"
FailoverStrategy::FailoverStrategy(const std::vector<Url*> &urls, int retryPause, int retries, IStrategyListener *listener, bool quiet) :
FailoverStrategy::FailoverStrategy(const std::vector<Pool> &urls, int retryPause, int retries, IStrategyListener *listener, bool quiet) :
m_quiet(quiet),
m_retries(retries),
m_retryPause(retryPause),
@@ -36,7 +36,7 @@ FailoverStrategy::FailoverStrategy(const std::vector<Url*> &urls, int retryPause
m_index(0),
m_listener(listener)
{
for (const Url *url : urls) {
for (const Pool &url : urls) {
add(url);
}
}
@@ -153,10 +153,10 @@ void FailoverStrategy::onResultAccepted(Client *client, const SubmitResult &resu
}
void FailoverStrategy::add(const Url *url)
void FailoverStrategy::add(const Pool &pool)
{
Client *client = new Client((int) m_pools.size(), Platform::userAgent(), this);
client->setUrl(url);
client->setPool(pool);
client->setRetryPause(m_retryPause * 1000);
client->setQuiet(m_quiet);

View File

@@ -30,6 +30,7 @@
#include "interfaces/IClientListener.h"
#include "interfaces/IStrategy.h"
#include "net/Pool.h"
class Client;
@@ -40,7 +41,7 @@ class Url;
class FailoverStrategy : public IStrategy, public IClientListener
{
public:
FailoverStrategy(const std::vector<Url*> &urls, int retryPause, int retries, IStrategyListener *listener, bool quiet = false);
FailoverStrategy(const std::vector<Pool> &urls, int retryPause, int retries, IStrategyListener *listener, bool quiet = false);
~FailoverStrategy();
public:
@@ -59,7 +60,7 @@ protected:
void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override;
private:
void add(const Url *url);
void add(const Pool &pool);
const bool m_quiet;
const int m_retries;

View File

@@ -22,18 +22,18 @@
*/
#include "common/Platform.h"
#include "interfaces/IStrategyListener.h"
#include "net/Client.h"
#include "net/strategies/SinglePoolStrategy.h"
#include "Platform.h"
SinglePoolStrategy::SinglePoolStrategy(const Url *url, int retryPause, IStrategyListener *listener, bool quiet) :
SinglePoolStrategy::SinglePoolStrategy(const Pool &pool, int retryPause, IStrategyListener *listener, bool quiet) :
m_active(false),
m_listener(listener)
{
m_client = new Client(0, Platform::userAgent(), this);
m_client->setUrl(url);
m_client->setPool(pool);
m_client->setRetryPause(retryPause * 1000);
m_client->setQuiet(quiet);
}

View File

@@ -37,7 +37,7 @@ class Url;
class SinglePoolStrategy : public IStrategy, public IClientListener
{
public:
SinglePoolStrategy(const Url *url, int retryPause, IStrategyListener *listener, bool quiet = false);
SinglePoolStrategy(const Pool &pool, int retryPause, IStrategyListener *listener, bool quiet = false);
~SinglePoolStrategy();
public:

View File

@@ -27,7 +27,7 @@
#define APP_ID "xmrig"
#define APP_NAME "XMRig"
#define APP_DESC "XMRig CPU miner"
#define APP_VERSION "2.6.0-beta1"
#define APP_VERSION "2.6.0-beta3"
#define APP_DOMAIN "xmrig.com"
#define APP_SITE "www.xmrig.com"
#define APP_COPYRIGHT "Copyright (C) 2016-2018 xmrig.com"
@@ -36,7 +36,7 @@
#define APP_VER_MAJOR 2
#define APP_VER_MINOR 6
#define APP_VER_BUILD 0
#define APP_VER_REV 1
#define APP_VER_REV 3
#ifdef _MSC_VER
# if (_MSC_VER >= 1910)

View File

@@ -24,7 +24,7 @@
#include <assert.h>
#include "core/CommonConfig.h"
#include "net/Pool.h"
#include "rapidjson/document.h"
#include "workers/CpuThread.h"
@@ -54,6 +54,12 @@ xmrig::CpuThread::~CpuThread()
}
bool xmrig::CpuThread::isSoftAES(AlgoVariant av)
{
return av == AV_SINGLE_SOFT || av == AV_DOUBLE_SOFT || av > AV_PENTA;
}
xmrig::CpuThread::cn_hash_fun xmrig::CpuThread::fn(Algo algorithm, AlgoVariant av, Variant variant)
{
assert(variant == VARIANT_NONE || variant == VARIANT_V1);
@@ -138,42 +144,6 @@ xmrig::CpuThread *xmrig::CpuThread::createFromAV(size_t index, Algo algorithm, A
{
assert(av > AV_AUTO && av < AV_MAX);
Multiway multiway = SingleWay;
bool softAES = false;
switch (av) {
case AV_SINGLE_SOFT:
softAES = true;
break;
case AV_DOUBLE:
multiway = DoubleWay;
case AV_DOUBLE_SOFT:
softAES = true;
break;
case AV_TRIPLE:
multiway = TripleWay;
case AV_TRIPLE_SOFT:
softAES = true;
break;
case AV_QUAD:
multiway = QuadWay;
case AV_QUAD_SOFT:
softAES = true;
break;
case AV_PENTA:
multiway = PentaWay;
case AV_PENTA_SOFT:
softAES = true;
break;
default:
break;
}
int64_t cpuId = -1L;
if (affinity != -1L) {
@@ -193,18 +163,96 @@ xmrig::CpuThread *xmrig::CpuThread::createFromAV(size_t index, Algo algorithm, A
}
}
return new CpuThread(index, algorithm, av, multiway, cpuId, priority, softAES, false);
return new CpuThread(index, algorithm, av, multiway(av), cpuId, priority, isSoftAES(av), false);
}
xmrig::CpuThread *xmrig::CpuThread::createFromData(size_t index, Algo algorithm, const CpuThread::Data &data, int priority, bool softAES)
{
int av = AV_AUTO;
const Multiway multiway = data.multiway;
if (multiway <= DoubleWay) {
av = softAES ? (multiway + 2) : multiway;
}
else {
av = softAES ? (multiway + 5) : (multiway + 2);
}
assert(av > AV_AUTO && av < AV_MAX);
return new CpuThread(index, algorithm, static_cast<AlgoVariant>(av), multiway, data.affinity, priority, softAES, false);
}
xmrig::CpuThread::Data xmrig::CpuThread::parse(const rapidjson::Value &object)
{
Data data;
const auto &multiway = object["low_power_mode"];
if (multiway.IsBool()) {
data.multiway = multiway.IsTrue() ? DoubleWay : SingleWay;
data.valid = true;
}
else if (multiway.IsUint()) {
data.setMultiway(multiway.GetInt());
}
if (!data.valid) {
return data;
}
const auto &affinity = object["affine_to_cpu"];
if (affinity.IsUint64()) {
data.affinity = affinity.GetInt64();
}
return data;
}
xmrig::IThread::Multiway xmrig::CpuThread::multiway(AlgoVariant av)
{
switch (av) {
case AV_SINGLE:
case AV_SINGLE_SOFT:
return SingleWay;
case AV_DOUBLE_SOFT:
case AV_DOUBLE:
return DoubleWay;
case AV_TRIPLE_SOFT:
case AV_TRIPLE:
return TripleWay;
case AV_QUAD_SOFT:
case AV_QUAD:
return QuadWay;
case AV_PENTA_SOFT:
case AV_PENTA:
return PentaWay;
default:
break;
}
return SingleWay;
}
#ifndef XMRIG_NO_API
rapidjson::Value xmrig::CpuThread::toAPI(rapidjson::Document &doc) const
{
rapidjson::Value obj(rapidjson::kObjectType);
using namespace rapidjson;
Value obj(kObjectType);
auto &allocator = doc.GetAllocator();
obj.AddMember("type", "cpu", allocator);
obj.AddMember("algo", rapidjson::StringRef(CommonConfig::algoName(algorithm())), allocator);
obj.AddMember("algo", rapidjson::StringRef(Pool::algoName(algorithm())), allocator);
obj.AddMember("av", m_av, allocator);
obj.AddMember("low_power_mode", multiway(), allocator);
obj.AddMember("affine_to_cpu", affinity(), allocator);
@@ -214,3 +262,17 @@ rapidjson::Value xmrig::CpuThread::toAPI(rapidjson::Document &doc) const
return obj;
}
#endif
rapidjson::Value xmrig::CpuThread::toConfig(rapidjson::Document &doc) const
{
using namespace rapidjson;
Value obj(kObjectType);
auto &allocator = doc.GetAllocator();
obj.AddMember("low_power_mode", multiway(), allocator);
obj.AddMember("affine_to_cpu", affinity() == -1L ? Value(kFalseType) : Value(affinity()), allocator);
return obj;
}

View File

@@ -25,8 +25,8 @@
#define __CPUTHREAD_H__
#include "common/xmrig.h"
#include "interfaces/IThread.h"
#include "xmrig.h"
struct cryptonight_ctx;
@@ -38,37 +38,54 @@ namespace xmrig {
class CpuThread : public IThread
{
public:
enum Multiway {
SingleWay = 1,
DoubleWay,
TripleWay,
QuadWay,
PentaWay
struct Data
{
inline Data() : valid(false), affinity(-1L), multiway(SingleWay) {}
inline void setMultiway(int value)
{
if (value >= SingleWay && value <= PentaWay) {
multiway = static_cast<Multiway>(value);
valid = true;
}
}
bool valid;
int64_t affinity;
Multiway multiway;
};
CpuThread(size_t index, Algo algorithm, AlgoVariant av, Multiway multiway, int64_t affinity, int priority, bool softAES, bool prefetch);
~CpuThread();
typedef void (*cn_hash_fun)(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx);
typedef void (*cn_hash_fun)(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx **ctx);
static bool isSoftAES(AlgoVariant av);
static cn_hash_fun fn(Algo algorithm, AlgoVariant av, Variant variant);
static CpuThread *createFromAV(size_t index, Algo algorithm, AlgoVariant av, int64_t affinity, int priority);
static CpuThread *createFromData(size_t index, Algo algorithm, const CpuThread::Data &data, int priority, bool softAES);
static Data parse(const rapidjson::Value &object);
static Multiway multiway(AlgoVariant av);
inline bool isPrefetch() const { return m_prefetch; }
inline bool isSoftAES() const { return m_softAES; }
inline cn_hash_fun fn(Variant variant) const { return fn(m_algorithm, m_av, variant); }
inline Algo algorithm() const override { return m_algorithm; }
inline int multiway() const override { return m_multiway; }
inline int priority() const override { return m_priority; }
inline int64_t affinity() const override { return m_affinity; }
inline Multiway multiway() const override { return m_multiway; }
inline size_t index() const override { return m_index; }
inline Type type() const override { return CPU; }
protected:
# ifndef XMRIG_NO_API
rapidjson::Value toAPI(rapidjson::Document &doc) const override;
# endif
rapidjson::Value toConfig(rapidjson::Document &doc) const override;
private:
const Algo m_algorithm;
const AlgoVariant m_av;

View File

@@ -25,11 +25,10 @@
#include "workers/Handle.h"
Handle::Handle(xmrig::IThread *config, size_t totalThreads, size_t totalWays, int64_t affinity) :
m_affinity(affinity),
Handle::Handle(xmrig::IThread *config, uint32_t offset, size_t totalWays) :
m_worker(nullptr),
m_totalThreads(totalThreads),
m_totalWays(totalWays),
m_offset(offset),
m_config(config)
{
}

View File

@@ -25,6 +25,7 @@
#define __HANDLE_H__
#include <assert.h>
#include <stdint.h>
#include <uv.h>
@@ -38,23 +39,21 @@ class IWorker;
class Handle
{
public:
Handle(xmrig::IThread *config, size_t totalThreads, size_t totalWays, int64_t affinity);
Handle(xmrig::IThread *config, uint32_t offset, size_t totalWays);
void join();
void start(void (*callback) (void *));
inline int64_t affinity() const { return m_affinity; }
inline IWorker *worker() const { return m_worker; }
inline size_t threadId() const { return m_config->index(); }
inline size_t totalThreads() const { return m_totalThreads; }
inline size_t totalWays() const { return m_totalWays; }
inline void setWorker(IWorker *worker) { m_worker = worker; }
inline uint32_t offset() const { return m_offset; }
inline void setWorker(IWorker *worker) { assert(worker != nullptr); m_worker = worker; }
inline xmrig::IThread *config() const { return m_config; }
private:
int64_t m_affinity;
IWorker *m_worker;
size_t m_totalThreads;
size_t m_totalWays;
uint32_t m_offset;
uv_thread_t m_thread;
xmrig::IThread *m_config;
};

View File

@@ -22,6 +22,7 @@
*/
#include <assert.h>
#include <chrono>
#include <math.h>
#include <memory.h>
@@ -45,7 +46,7 @@ inline const char *format(double h, char* buf, size_t size)
}
Hashrate::Hashrate(int threads, xmrig::Controller *controller) :
Hashrate::Hashrate(size_t threads, xmrig::Controller *controller) :
m_highest(0.0),
m_threads(threads),
m_controller(controller)
@@ -54,13 +55,10 @@ Hashrate::Hashrate(int threads, xmrig::Controller *controller) :
m_timestamps = new uint64_t*[threads];
m_top = new uint32_t[threads];
for (int i = 0; i < threads; i++) {
m_counts[i] = new uint64_t[kBucketSize];
m_timestamps[i] = new uint64_t[kBucketSize];
m_top[i] = 0;
memset(m_counts[0], 0, sizeof(uint64_t) * kBucketSize);
memset(m_timestamps[0], 0, sizeof(uint64_t) * kBucketSize);
for (size_t i = 0; i < threads; i++) {
m_counts[i] = new uint64_t[kBucketSize]();
m_timestamps[i] = new uint64_t[kBucketSize]();
m_top[i] = 0;
}
const int printTime = controller->config()->printTime();
@@ -79,7 +77,7 @@ double Hashrate::calc(size_t ms) const
double result = 0.0;
double data;
for (int i = 0; i < m_threads; ++i) {
for (size_t i = 0; i < m_threads; ++i) {
data = calc(i, ms);
if (isnormal(data)) {
result += data;
@@ -92,6 +90,8 @@ double Hashrate::calc(size_t ms) const
double Hashrate::calc(size_t threadId, size_t ms) const
{
assert(threadId < m_threads);
using namespace std::chrono;
const uint64_t now = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();

View File

@@ -43,7 +43,7 @@ public:
LargeInterval = 900000
};
Hashrate(int threads, xmrig::Controller *controller);
Hashrate(size_t threads, xmrig::Controller *controller);
double calc(size_t ms) const;
double calc(size_t threadId, size_t ms) const;
void add(size_t threadId, uint64_t count, uint64_t timestamp);
@@ -52,7 +52,7 @@ public:
void updateHighest();
inline double highest() const { return m_highest; }
inline int threads() const { return m_threads; }
inline size_t threads() const { return m_threads; }
private:
static void onReport(uv_timer_t *handle);
@@ -61,7 +61,7 @@ private:
constexpr static size_t kBucketMask = kBucketSize - 1;
double m_highest;
int m_threads;
size_t m_threads;
uint32_t* m_top;
uint64_t** m_counts;
uint64_t** m_timestamps;

View File

@@ -28,46 +28,59 @@
#include "crypto/CryptoNight_test.h"
#include "workers/CpuThread.h"
#include "workers/DoubleWorker.h"
#include "workers/MultiWorker.h"
#include "workers/Workers.h"
class DoubleWorker::State
{
public:
inline State() :
nonce1(0),
nonce2(0)
{}
Job job;
uint32_t nonce1;
uint32_t nonce2;
uint8_t blob[84 * 2];
};
DoubleWorker::DoubleWorker(Handle *handle)
template<size_t N>
MultiWorker<N>::MultiWorker(Handle *handle)
: Worker(handle)
{
m_state = new State();
m_pausedState = new State();
m_memory = Mem::create(m_ctx, m_thread->algorithm(), N);
}
DoubleWorker::~DoubleWorker()
template<size_t N>
MultiWorker<N>::~MultiWorker()
{
delete m_state;
delete m_pausedState;
Mem::release(m_ctx, N, m_memory);
}
bool DoubleWorker::start()
template<size_t N>
bool MultiWorker<N>::selfTest()
{
if (!selfTest()) {
if (m_thread->fn(xmrig::VARIANT_NONE) == nullptr) {
return false;
}
m_thread->fn(xmrig::VARIANT_NONE)(test_input, 76, m_hash, m_ctx);
if (m_thread->algorithm() == xmrig::CRYPTONIGHT && memcmp(m_hash, test_output_v0, sizeof m_hash) == 0) {
m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_hash, m_ctx);
return memcmp(m_hash, test_output_v1, sizeof m_hash) == 0;
}
# ifndef XMRIG_NO_AEON
if (m_thread->algorithm() == xmrig::CRYPTONIGHT_LITE && memcmp(m_hash, test_output_v0_lite, sizeof m_hash) == 0) {
m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_hash, m_ctx);
return memcmp(m_hash, test_output_v1_lite, sizeof m_hash) == 0;
}
# endif
# ifndef XMRIG_NO_SUMO
return m_thread->algorithm() == xmrig::CRYPTONIGHT_HEAVY && memcmp(m_hash, test_output_heavy, sizeof m_hash) == 0;
# else
return false;
# endif
}
template<size_t N>
void MultiWorker<N>::start()
{
while (Workers::sequence() > 0) {
if (Workers::isPaused()) {
do {
@@ -83,38 +96,35 @@ bool DoubleWorker::start()
}
while (!Workers::isOutdated(m_sequence)) {
if ((m_count & 0xF) == 0) {
if ((m_count & 0x7) == 0) {
storeStats();
}
m_count += 2;
*Job::nonce(m_state->blob) = ++m_state->nonce1;
*Job::nonce(m_state->blob + m_state->job.size()) = ++m_state->nonce2;
m_thread->fn(m_state.job.variant())(m_state.blob, m_state.job.size(), m_hash, m_ctx);
m_thread->fn(m_state->job.variant())(m_state->blob, m_state->job.size(), m_hash, m_ctx);
for (size_t i = 0; i < N; ++i) {
if (*reinterpret_cast<uint64_t*>(m_hash + (i * 32) + 24) < m_state.job.target()) {
Workers::submit(JobResult(m_state.job.poolId(), m_state.job.id(), *nonce(i), m_hash + (i * 32), m_state.job.diff()));
}
if (*reinterpret_cast<uint64_t*>(m_hash + 24) < m_state->job.target()) {
Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce1, m_hash, m_state->job.diff()));
*nonce(i) += 1;
}
if (*reinterpret_cast<uint64_t*>(m_hash + 32 + 24) < m_state->job.target()) {
Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce2, m_hash + 32, m_state->job.diff()));
}
m_count += N;
std::this_thread::yield();
}
consumeJob();
}
return true;
}
bool DoubleWorker::resume(const Job &job)
template<size_t N>
bool MultiWorker<N>::resume(const Job &job)
{
if (m_state->job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_pausedState->job.id()) {
*m_state = *m_pausedState;
if (m_state.job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_pausedState.job.id()) {
m_state = m_pausedState;
return true;
}
@@ -122,37 +132,12 @@ bool DoubleWorker::resume(const Job &job)
}
bool DoubleWorker::selfTest()
{
if (m_thread->fn(xmrig::VARIANT_NONE) == nullptr) {
return false;
}
m_thread->fn(xmrig::VARIANT_NONE)(test_input, 76, m_hash, m_ctx);
if (m_thread->algorithm() == xmrig::CRYPTONIGHT && memcmp(m_hash, test_output_v0, 64) == 0) {
m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_hash, m_ctx);
return memcmp(m_hash, test_output_v1, 64) == 0;
}
# ifndef XMRIG_NO_AEON
if (m_thread->algorithm() == xmrig::CRYPTONIGHT_LITE && memcmp(m_hash, test_output_v0_lite, 64) == 0) {
m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_hash, m_ctx);
return memcmp(m_hash, test_output_v1_lite, 64) == 0;
}
# endif
return memcmp(m_hash, test_output_heavy, 64) == 0;
}
void DoubleWorker::consumeJob()
template<size_t N>
void MultiWorker<N>::consumeJob()
{
Job job = Workers::job();
m_sequence = Workers::sequence();
if (m_state->job == job) {
if (m_state.job == job) {
return;
}
@@ -162,24 +147,39 @@ void DoubleWorker::consumeJob()
return;
}
m_state->job = std::move(job);
memcpy(m_state->blob, m_state->job.blob(), m_state->job.size());
memcpy(m_state->blob + m_state->job.size(), m_state->job.blob(), m_state->job.size());
m_state.job = job;
if (m_state->job.isNicehash()) {
m_state->nonce1 = (*Job::nonce(m_state->blob) & 0xff000000U) + (0xffffffU / m_totalWays * m_id);
m_state->nonce2 = (*Job::nonce(m_state->blob + m_state->job.size()) & 0xff000000U) + (0xffffffU / m_totalWays * (m_id + m_totalThreads));
const size_t size = m_state.job.size();
memcpy(m_state.blob, m_state.job.blob(), m_state.job.size());
if (N > 1) {
for (size_t i = 1; i < N; ++i) {
memcpy(m_state.blob + (i * size), m_state.blob, size);
}
}
else {
m_state->nonce1 = 0xffffffffU / m_totalWays * m_id;
m_state->nonce2 = 0xffffffffU / m_totalWays * (m_id + m_totalThreads);
for (size_t i = 0; i < N; ++i) {
if (m_state.job.isNicehash()) {
*nonce(i) = (*nonce(i) & 0xff000000U) + (0xffffffU / m_totalWays * (m_offset + i));
}
else {
*nonce(i) = 0xffffffffU / m_totalWays * (m_offset + i);
}
}
}
void DoubleWorker::save(const Job &job)
template<size_t N>
void MultiWorker<N>::save(const Job &job)
{
if (job.poolId() == -1 && m_state->job.poolId() >= 0) {
*m_pausedState = *m_state;
if (job.poolId() == -1 && m_state.job.poolId() >= 0) {
m_pausedState = m_state;
}
}
template class MultiWorker<1>;
template class MultiWorker<2>;
template class MultiWorker<3>;
template class MultiWorker<4>;
template class MultiWorker<5>;

View File

@@ -22,10 +22,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __DOUBLEWORKER_H__
#define __DOUBLEWORKER_H__
#ifndef __MULTIWORKER_H__
#define __MULTIWORKER_H__
#include "Mem.h"
#include "net/Job.h"
#include "net/JobResult.h"
#include "workers/Worker.h"
@@ -34,26 +35,39 @@
class Handle;
class DoubleWorker : public Worker
template<size_t N>
class MultiWorker : public Worker
{
public:
DoubleWorker(Handle *handle);
~DoubleWorker();
MultiWorker(Handle *handle);
~MultiWorker();
bool start() override;
protected:
bool selfTest() override;
void start() override;
private:
bool resume(const Job &job);
bool selfTest();
void consumeJob();
void save(const Job &job);
class State;
inline uint32_t *nonce(size_t index)
{
return reinterpret_cast<uint32_t*>(m_state.blob + (index * m_state.job.size()) + 39);
}
uint8_t m_hash[64];
State *m_state;
State *m_pausedState;
struct State
{
alignas(16) uint8_t blob[96 * N];
Job job;
};
cryptonight_ctx *m_ctx[N];
State m_pausedState;
State m_state;
uint8_t m_hash[N * 32];
};
#endif /* __SINGLEWORKER_H__ */
#endif /* __MULTIWORKER_H__ */

View File

@@ -1,154 +0,0 @@
/* 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 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2016-2018 XMRig <https://github.com/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 <thread>
#include "crypto/CryptoNight_test.h"
#include "workers/CpuThread.h"
#include "workers/SingleWorker.h"
#include "workers/Workers.h"
SingleWorker::SingleWorker(Handle *handle)
: Worker(handle)
{
}
bool SingleWorker::start()
{
if (!selfTest()) {
return false;
}
while (Workers::sequence() > 0) {
if (Workers::isPaused()) {
do {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
while (Workers::isPaused());
if (Workers::sequence() == 0) {
break;
}
consumeJob();
}
while (!Workers::isOutdated(m_sequence)) {
if ((m_count & 0xF) == 0) {
storeStats();
}
m_count++;
*m_job.nonce() = ++m_result.nonce;
m_thread->fn(m_job.variant())(m_job.blob(), m_job.size(), m_result.result, m_ctx);
if (*reinterpret_cast<uint64_t*>(m_result.result + 24) < m_job.target()) {
Workers::submit(m_result);
}
std::this_thread::yield();
}
consumeJob();
}
return true;
}
bool SingleWorker::resume(const Job &job)
{
if (m_job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_paused.id()) {
m_job = m_paused;
m_result = m_job;
m_result.nonce = *m_job.nonce();
return true;
}
return false;
}
bool SingleWorker::selfTest()
{
if (m_thread->fn(xmrig::VARIANT_NONE) == nullptr) {
return false;
}
m_thread->fn(xmrig::VARIANT_NONE)(test_input, 76, m_result.result, m_ctx);
if (m_thread->algorithm() == xmrig::CRYPTONIGHT && memcmp(m_result.result, test_output_v0, 32) == 0) {
m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_result.result, m_ctx);
return memcmp(m_result.result, test_output_v1, 32) == 0;
}
# ifndef XMRIG_NO_AEON
if (m_thread->algorithm() == xmrig::CRYPTONIGHT_LITE && memcmp(m_result.result, test_output_v0_lite, 32) == 0) {
m_thread->fn(xmrig::VARIANT_V1)(test_input, 76, m_result.result, m_ctx);
return memcmp(m_result.result, test_output_v1_lite, 32) == 0;
}
# endif
return memcmp(m_result.result, test_output_heavy, 32) == 0;
}
void SingleWorker::consumeJob()
{
Job job = Workers::job();
m_sequence = Workers::sequence();
if (m_job == job) {
return;
}
save(job);
if (resume(job)) {
return;
}
m_job = std::move(job);
m_result = m_job;
if (m_job.isNicehash()) {
m_result.nonce = (*m_job.nonce() & 0xff000000U) + (0xffffffU / m_totalWays * m_id);
}
else {
m_result.nonce = 0xffffffffU / m_totalWays * m_id;
}
}
void SingleWorker::save(const Job &job)
{
if (job.poolId() == -1 && m_job.poolId() >= 0) {
m_paused = m_job;
}
}

View File

@@ -24,9 +24,8 @@
#include <chrono>
#include "common/Platform.h"
#include "Cpu.h"
#include "Mem.h"
#include "Platform.h"
#include "workers/CpuThread.h"
#include "workers/Handle.h"
#include "workers/Worker.h"
@@ -34,25 +33,19 @@
Worker::Worker(Handle *handle) :
m_id(handle->threadId()),
m_totalThreads(handle->totalThreads()),
m_totalWays(handle->totalWays()),
m_offset(handle->offset()),
m_hashCount(0),
m_timestamp(0),
m_count(0),
m_sequence(0),
m_thread(static_cast<xmrig::CpuThread *>(handle->config()))
{
if (Cpu::threads() > 1 && handle->affinity() != -1L) {
Cpu::setAffinity(m_id, handle->affinity());
if (Cpu::threads() > 1 && m_thread->affinity() != -1L) {
Platform::setThreadAffinity(m_thread->affinity());
}
Platform::setThreadPriority(handle->config()->priority());
m_ctx = Mem::create(m_id);
}
Worker::~Worker()
{
Platform::setThreadPriority(m_thread->priority());
}

View File

@@ -30,6 +30,7 @@
#include "interfaces/IWorker.h"
#include "Mem.h"
struct cryptonight_ctx;
@@ -45,8 +46,8 @@ class Worker : public IWorker
{
public:
Worker(Handle *handle);
~Worker();
inline const MemInfo &memory() const { return m_memory; }
inline size_t id() const override { return m_id; }
inline uint64_t hashCount() const override { return m_hashCount.load(std::memory_order_relaxed); }
inline uint64_t timestamp() const override { return m_timestamp.load(std::memory_order_relaxed); }
@@ -54,10 +55,10 @@ public:
protected:
void storeStats();
cryptonight_ctx *m_ctx;
size_t m_id;
size_t m_totalThreads;
size_t m_totalWays;
const size_t m_id;
const size_t m_totalWays;
const uint32_t m_offset;
MemInfo m_memory;
std::atomic<uint64_t> m_hashCount;
std::atomic<uint64_t> m_timestamp;
uint64_t m_count;

View File

@@ -28,23 +28,24 @@
#include "api/Api.h"
#include "core/Config.h"
#include "core/Controller.h"
#include "crypto/CryptoNight_constants.h"
#include "interfaces/IJobResultListener.h"
#include "interfaces/IThread.h"
#include "log/Log.h"
#include "Mem.h"
#include "workers/DoubleWorker.h"
#include "rapidjson/document.h"
#include "workers/Handle.h"
#include "workers/Hashrate.h"
#include "workers/SingleWorker.h"
#include "workers/MultiWorker.h"
#include "workers/Workers.h"
#include "log/Log.h"
bool Workers::m_active = false;
bool Workers::m_enabled = true;
Hashrate *Workers::m_hashrate = nullptr;
IJobResultListener *Workers::m_listener = nullptr;
Job Workers::m_job;
Workers::LaunchStatus Workers::m_status;
std::atomic<int> Workers::m_paused;
std::atomic<uint64_t> Workers::m_sequence;
std::list<JobResult> Workers::m_queue;
@@ -66,6 +67,26 @@ Job Workers::job()
}
size_t Workers::hugePages()
{
uv_mutex_lock(&m_mutex);
const size_t hugePages = m_status.hugePages;
uv_mutex_unlock(&m_mutex);
return hugePages;
}
size_t Workers::threads()
{
uv_mutex_lock(&m_mutex);
const size_t threads = m_status.threads;
uv_mutex_unlock(&m_mutex);
return threads;
}
void Workers::printHashrate(bool detail)
{
m_hashrate->print();
@@ -111,10 +132,12 @@ void Workers::setJob(const Job &job, bool donate)
void Workers::start(xmrig::Controller *controller)
{
const std::vector<xmrig::IThread *> &threads = controller->config()->threads();
m_status.algo = controller->config()->algorithm();
m_status.colors = controller->config()->isHugePages();
m_status.threads = threads.size();
size_t totalWays = 0;
for (const xmrig::IThread *thread : threads) {
totalWays += thread->multiway();
m_status.ways += thread->multiway();
}
m_hashrate = new Hashrate(threads.size(), controller);
@@ -129,8 +152,12 @@ void Workers::start(xmrig::Controller *controller)
uv_timer_init(uv_default_loop(), &m_timer);
uv_timer_start(&m_timer, Workers::onTick, 500, 500);
uint32_t offset = 0;
for (xmrig::IThread *thread : threads) {
Handle *handle = new Handle(thread, threads.size(), totalWays, controller->config()->affinity());
Handle *handle = new Handle(thread, offset, m_status.ways);
offset += thread->multiway();
m_workers.push_back(handle);
handle->start(Workers::onReady);
}
@@ -162,23 +189,66 @@ void Workers::submit(const JobResult &result)
}
#ifndef XMRIG_NO_API
void Workers::threadsSummary(rapidjson::Document &doc)
{
uv_mutex_lock(&m_mutex);
const uint64_t pages[2] = { m_status.hugePages, m_status.pages };
const uint64_t memory = m_status.ways * xmrig::cn_select_memory(m_status.algo);
uv_mutex_unlock(&m_mutex);
auto &allocator = doc.GetAllocator();
rapidjson::Value hugepages(rapidjson::kArrayType);
hugepages.PushBack(pages[0], allocator);
hugepages.PushBack(pages[1], allocator);
doc.AddMember("hugepages", hugepages, allocator);
doc.AddMember("memory", memory, allocator);
}
#endif
void Workers::onReady(void *arg)
{
auto handle = static_cast<Handle*>(arg);
if (Mem::isDoubleHash()) {
handle->setWorker(new DoubleWorker(handle));
}
else {
handle->setWorker(new SingleWorker(handle));
IWorker *worker = nullptr;
switch (handle->config()->multiway()) {
case 1:
worker = new MultiWorker<1>(handle);
break;
case 2:
worker = new MultiWorker<2>(handle);
break;
case 3:
worker = new MultiWorker<3>(handle);
break;
case 4:
worker = new MultiWorker<4>(handle);
break;
case 5:
worker = new MultiWorker<5>(handle);
break;
default:
break;
}
const bool rc = handle->worker()->start();
handle->setWorker(worker);
if (!rc) {
uv_mutex_lock(&m_mutex);
if (!worker->selfTest()) {
LOG_ERR("thread %zu error: \"hash self-test failed\".", handle->worker()->id());
uv_mutex_unlock(&m_mutex);
return;
}
start(worker);
}
@@ -214,8 +284,35 @@ void Workers::onTick(uv_timer_t *handle)
if ((m_ticks++ & 0xF) == 0) {
m_hashrate->updateHighest();
}
# ifndef XMRIG_NO_API
Api::tick(m_hashrate);
# endif
}
void Workers::start(IWorker *worker)
{
const Worker *w = static_cast<const Worker *>(worker);
uv_mutex_lock(&m_mutex);
m_status.started++;
m_status.pages += w->memory().pages;
m_status.hugePages += w->memory().hugePages;
if (m_status.started == m_status.threads) {
const double percent = (double) m_status.hugePages / m_status.pages * 100.0;
const size_t memory = m_status.ways * xmrig::cn_select_memory(m_status.algo) / 1048576;
if (m_status.colors) {
LOG_INFO("\x1B[01;32mREADY (CPU)\x1B[0m threads \x1B[01;36m%zu(%zu)\x1B[0m huge pages %s%zu/%zu %1.0f%%\x1B[0m memory \x1B[01;36m%zu.0 MB",
m_status.threads, m_status.ways,
(m_status.hugePages == m_status.pages ? "\x1B[01;32m" : (m_status.hugePages == 0 ? "\x1B[01;31m" : "\x1B[01;33m")),
m_status.hugePages, m_status.pages, percent, memory);
}
else {
LOG_INFO("READY (CPU) threads %zu(%zu) huge pages %zu/%zu %f%% memory %zu.0 MB",
m_status.threads, m_status.ways, m_status.hugePages, m_status.pages, percent, memory);
}
}
uv_mutex_unlock(&m_mutex);
worker->start();
}

View File

@@ -32,11 +32,13 @@
#include "net/Job.h"
#include "net/JobResult.h"
#include "rapidjson/fwd.h"
class Handle;
class Hashrate;
class IJobResultListener;
class IWorker;
namespace xmrig {
@@ -48,6 +50,8 @@ class Workers
{
public:
static Job job();
static size_t hugePages();
static size_t threads();
static void printHashrate(bool detail);
static void setEnabled(bool enabled);
static void setJob(const Job &job, bool donate);
@@ -58,20 +62,49 @@ public:
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 isPaused() { return m_paused.load(std::memory_order_relaxed) == 1; }
static inline Hashrate *hashrate() { return m_hashrate; }
static inline uint64_t sequence() { return m_sequence.load(std::memory_order_relaxed); }
static inline void pause() { m_active = false; m_paused = 1; m_sequence++; }
static inline void setListener(IJobResultListener *listener) { m_listener = listener; }
# ifndef XMRIG_NO_API
static void threadsSummary(rapidjson::Document &doc);
# endif
private:
static void onReady(void *arg);
static void onResult(uv_async_t *handle);
static void onTick(uv_timer_t *handle);
static void start(IWorker *worker);
class LaunchStatus
{
public:
inline LaunchStatus() :
colors(true),
hugePages(0),
pages(0),
started(0),
threads(0),
ways(0),
algo(xmrig::CRYPTONIGHT)
{}
bool colors;
size_t hugePages;
size_t pages;
size_t started;
size_t threads;
size_t ways;
xmrig::Algo algo;
};
static bool m_active;
static bool m_enabled;
static Hashrate *m_hashrate;
static IJobResultListener *m_listener;
static Job m_job;
static LaunchStatus m_status;
static std::atomic<int> m_paused;
static std::atomic<uint64_t> m_sequence;
static std::list<JobResult> m_queue;