Compare commits

..

94 Commits

Author SHA1 Message Date
SChernykh 1ef88622d6 p2pool v3.6.2
C/C++ CI / build-alpine-static (map[arch:aarch64 flags:-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline]) (push) Has been cancelled
C/C++ CI / build-alpine-static (map[arch:x86_64 flags:-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline]) (push) Has been cancelled
C/C++ CI / build-ubuntu (map[c:gcc-11 cpp:g++-11 os:ubuntu-20.04]) (push) Has been cancelled
C/C++ CI / build-ubuntu (map[c:gcc-12 cpp:g++-12 os:ubuntu-22.04]) (push) Has been cancelled
C/C++ CI / build-ubuntu-static-libs (map[flags:-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline]) (push) Has been cancelled
C/C++ CI / build-ubuntu-aarch64 (map[flags:-flto=2 -fuse-linker-plugin -ffunction-sections os:ubuntu-20.04]) (push) Has been cancelled
C/C++ CI / build-ubuntu-aarch64 (map[flags:-flto=2 -fuse-linker-plugin -ffunction-sections os:ubuntu-22.04]) (push) Has been cancelled
C/C++ CI / build-windows-msys2 (map[c:clang cxx:clang++ flags:-flto -ffunction-sections -fuse-ld=lld -Wno-unused-command-line-argument]) (push) Has been cancelled
C/C++ CI / build-windows-msys2 (map[c:gcc cxx:g++ flags:-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=maybe-uninitialized -Wno-error=attributes]) (push) Has been cancelled
C/C++ CI / build-windows-msbuild (map[msbuild:C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\amd64\ os:2019 rx:OFF upnp:OFF vs:Visual Studio 16 2019]) (push) Has been cancelled
C/C++ CI / build-windows-msbuild (map[msbuild:C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\amd64\ os:2019 rx:OFF upnp:ON vs:Visual Studio 16 2019]) (push) Has been cancelled
C/C++ CI / build-windows-msbuild (map[msbuild:C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\amd64\ os:2019 rx:ON upnp:ON vs:Visual Studio 16 2019]) (push) Has been cancelled
C/C++ CI / build-macos (push) Has been cancelled
C/C++ CI / build-macos-aarch64 (push) Has been cancelled
C/C++ CI / build-freebsd (map[architecture:x86-64 host:ubuntu-22.04 name:freebsd version:12.4]) (push) Has been cancelled
C/C++ CI / build-openbsd (map[architecture:x86-64 host:ubuntu-22.04 name:openbsd version:7.2]) (push) Has been cancelled
clang-tidy / clang-tidy (push) Has been cancelled
CodeQL / Analyze (cpp) (push) Has been cancelled
cppcheck / cppcheck-ubuntu (push) Has been cancelled
cppcheck / cppcheck-windows (push) Has been cancelled
Microsoft C++ Code Analysis / Analyze (push) Has been cancelled
source-snapshot / source-snapshot (push) Has been cancelled
Sync test / sync-test-ubuntu-tsan (push) Has been cancelled
Sync test / sync-test-ubuntu-msan (push) Has been cancelled
Sync test / sync-test-ubuntu-ubsan (push) Has been cancelled
Sync test / sync-test-ubuntu-asan (push) Has been cancelled
Sync test / sync-test-macos (push) Has been cancelled
Sync test / sync-test-windows-debug-asan (push) Has been cancelled
Sync test / sync-test-windows-leaks (push) Has been cancelled
2023-09-03 09:49:31 +02:00
SChernykh b1d3fb63f3 Use the old compiler for macOS-aarch64 build 2023-09-02 18:41:11 +02:00
SChernykh f44ffd1959 Sync test: rewrote stratum connection code 2023-09-01 18:20:50 +02:00
SChernykh e7545db663 Sync test: make sure stratum logs are saved 2023-09-01 17:12:22 +02:00
SChernykh fcf9d2ad15 p2pool v3.6.1
C/C++ CI / build-alpine-static (map[arch:aarch64 flags:-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline]) (push) Has been cancelled
C/C++ CI / build-alpine-static (map[arch:x86_64 flags:-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline]) (push) Has been cancelled
C/C++ CI / build-ubuntu (map[c:gcc-11 cpp:g++-11 os:ubuntu-20.04]) (push) Has been cancelled
C/C++ CI / build-ubuntu (map[c:gcc-12 cpp:g++-12 os:ubuntu-22.04]) (push) Has been cancelled
C/C++ CI / build-ubuntu-static-libs (map[flags:-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline]) (push) Has been cancelled
C/C++ CI / build-ubuntu-aarch64 (map[flags:-flto=2 -fuse-linker-plugin -ffunction-sections os:ubuntu-20.04]) (push) Has been cancelled
C/C++ CI / build-ubuntu-aarch64 (map[flags:-flto=2 -fuse-linker-plugin -ffunction-sections os:ubuntu-22.04]) (push) Has been cancelled
C/C++ CI / build-windows-msys2 (map[c:clang cxx:clang++ flags:-flto -ffunction-sections -fuse-ld=lld -Wno-unused-command-line-argument]) (push) Has been cancelled
C/C++ CI / build-windows-msys2 (map[c:gcc cxx:g++ flags:-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=maybe-uninitialized -Wno-error=attributes]) (push) Has been cancelled
C/C++ CI / build-windows-msbuild (map[msbuild:C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\amd64\ os:2019 rx:OFF upnp:OFF vs:Visual Studio 16 2019]) (push) Has been cancelled
C/C++ CI / build-windows-msbuild (map[msbuild:C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\amd64\ os:2019 rx:OFF upnp:ON vs:Visual Studio 16 2019]) (push) Has been cancelled
C/C++ CI / build-windows-msbuild (map[msbuild:C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\amd64\ os:2019 rx:ON upnp:ON vs:Visual Studio 16 2019]) (push) Has been cancelled
C/C++ CI / build-macos (push) Has been cancelled
C/C++ CI / build-macos-aarch64 (push) Has been cancelled
C/C++ CI / build-freebsd (map[architecture:x86-64 host:ubuntu-22.04 name:freebsd version:12.4]) (push) Has been cancelled
C/C++ CI / build-openbsd (map[architecture:x86-64 host:ubuntu-22.04 name:openbsd version:7.2]) (push) Has been cancelled
clang-tidy / clang-tidy (push) Has been cancelled
CodeQL / Analyze (cpp) (push) Has been cancelled
cppcheck / cppcheck-ubuntu (push) Has been cancelled
cppcheck / cppcheck-windows (push) Has been cancelled
Microsoft C++ Code Analysis / Analyze (push) Has been cancelled
source-snapshot / source-snapshot (push) Has been cancelled
Sync test / sync-test-ubuntu-tsan (push) Has been cancelled
Sync test / sync-test-ubuntu-msan (push) Has been cancelled
Sync test / sync-test-ubuntu-ubsan (push) Has been cancelled
Sync test / sync-test-ubuntu-asan (push) Has been cancelled
Sync test / sync-test-macos (push) Has been cancelled
Sync test / sync-test-windows-debug-asan (push) Has been cancelled
Sync test / sync-test-windows-leaks (push) Has been cancelled
2023-09-01 12:39:07 +02:00
SChernykh 7986321a52 Fixed console commands startup 2023-08-31 17:50:31 +02:00
SChernykh 8e0f28ee30 Fixed Windows 7 compatibility 2023-08-31 16:21:59 +02:00
SChernykh fecfa18999 p2pool v3.6
C/C++ CI / build-alpine-static (map[arch:aarch64 flags:-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline]) (push) Has been cancelled
C/C++ CI / build-alpine-static (map[arch:x86_64 flags:-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline]) (push) Has been cancelled
C/C++ CI / build-ubuntu (map[c:gcc-11 cpp:g++-11 os:ubuntu-20.04]) (push) Has been cancelled
C/C++ CI / build-ubuntu (map[c:gcc-12 cpp:g++-12 os:ubuntu-22.04]) (push) Has been cancelled
C/C++ CI / build-ubuntu-static-libs (map[flags:-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline]) (push) Has been cancelled
C/C++ CI / build-ubuntu-aarch64 (map[flags:-flto=2 -fuse-linker-plugin -ffunction-sections os:ubuntu-20.04]) (push) Has been cancelled
C/C++ CI / build-ubuntu-aarch64 (map[flags:-flto=2 -fuse-linker-plugin -ffunction-sections os:ubuntu-22.04]) (push) Has been cancelled
C/C++ CI / build-windows-msys2 (map[c:clang cxx:clang++ flags:-flto -ffunction-sections -fuse-ld=lld -Wno-unused-command-line-argument]) (push) Has been cancelled
C/C++ CI / build-windows-msys2 (map[c:gcc cxx:g++ flags:-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=maybe-uninitialized -Wno-error=attributes]) (push) Has been cancelled
C/C++ CI / build-windows-msbuild (map[msbuild:C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\amd64\ os:2019 rx:OFF upnp:OFF vs:Visual Studio 16 2019]) (push) Has been cancelled
C/C++ CI / build-windows-msbuild (map[msbuild:C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\amd64\ os:2019 rx:OFF upnp:ON vs:Visual Studio 16 2019]) (push) Has been cancelled
C/C++ CI / build-windows-msbuild (map[msbuild:C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\amd64\ os:2019 rx:ON upnp:ON vs:Visual Studio 16 2019]) (push) Has been cancelled
C/C++ CI / build-macos (push) Has been cancelled
C/C++ CI / build-macos-aarch64 (push) Has been cancelled
C/C++ CI / build-freebsd (map[architecture:x86-64 host:ubuntu-22.04 name:freebsd version:12.4]) (push) Has been cancelled
C/C++ CI / build-openbsd (map[architecture:x86-64 host:ubuntu-22.04 name:openbsd version:7.2]) (push) Has been cancelled
clang-tidy / clang-tidy (push) Has been cancelled
CodeQL / Analyze (cpp) (push) Has been cancelled
cppcheck / cppcheck-ubuntu (push) Has been cancelled
cppcheck / cppcheck-windows (push) Has been cancelled
Microsoft C++ Code Analysis / Analyze (push) Has been cancelled
source-snapshot / source-snapshot (push) Has been cancelled
Sync test / sync-test-ubuntu-tsan (push) Has been cancelled
Sync test / sync-test-ubuntu-msan (push) Has been cancelled
Sync test / sync-test-ubuntu-ubsan (push) Has been cancelled
Sync test / sync-test-ubuntu-asan (push) Has been cancelled
Sync test / sync-test-macos (push) Has been cancelled
Sync test / sync-test-windows-debug-asan (push) Has been cancelled
Sync test / sync-test-windows-leaks (push) Has been cancelled
2023-08-31 10:32:34 +02:00
SChernykh d8b23cd13c CI: fixed paths and file names 2023-08-26 21:00:23 +02:00
SChernykh 0e0101f507 CI: build libcxx_msan every time 2023-08-24 15:11:55 +02:00
SChernykh 17a17850ea Update libcxx_msan.tar.xz 2023-08-23 20:55:15 +02:00
SChernykh 71d4a6dab0 Tweaked macOS build parameters 2023-08-23 20:22:44 +02:00
SChernykh 936d3b5280 Added quick self-test 2023-08-23 17:01:01 +02:00
SChernykh fac9c23103 Fixed LTO in macOS builds 2023-08-23 16:23:48 +02:00
SChernykh 3674401923 Update RandomX 2023-08-23 13:37:07 +02:00
SChernykh 66d6d0dc33 CI: fixed BSD builds 2023-08-22 17:00:39 +02:00
SChernykh 31ce134413 Fixed INVALID SHARE log color 2023-08-21 21:24:04 +02:00
SChernykh b8e6aae289 Disabled RandomX tests 2023-08-21 20:49:45 +02:00
SChernykh 8f620712ef Update RandomX 2023-08-21 17:47:09 +02:00
SChernykh 1069d1c066 Fixed cppcheck error 2023-08-21 11:20:50 +02:00
SChernykh bc0634a541 RandomX: try to recover after an error 2023-08-21 11:01:57 +02:00
SChernykh 8d65a99fe4 Fixed data race 2023-08-18 21:57:51 +02:00
SChernykh 6e68714c26 CI: fixed libzmq cmake command line 2023-08-18 20:19:59 +02:00
SChernykh 06ff7b661a CI: added Alpine Linux static builds 2023-08-18 19:01:09 +02:00
SChernykh 70a6442b46 CI: reduced MacOS and FreeBSD binary sizes 2023-08-18 15:48:35 +02:00
SChernykh 9e7d394ae7 CI: reduced aarch64 binary sizes 2023-08-18 12:59:37 +02:00
SChernykh 326b2d7a04 Pool block test: check RandomX hash where possible 2023-08-18 12:01:14 +02:00
SChernykh f3045a5e80 Fixed possible thread handle leak 2023-08-17 10:16:51 +02:00
SChernykh b3d72cbfcb Update googletest 2023-08-16 14:55:48 +02:00
SChernykh 76c4573c39 CI: cleanup build warnings
Tests: fixed "unused const variable" warning
CMakeLists.txt: fixed deprecation warnings
2023-08-16 14:20:23 +02:00
SChernykh 741bec9874 CI: optimized msys2 binary sizes more 2023-08-16 12:03:48 +02:00
SChernykh 46aed06523 CI: optimized msys2 binary sizes 2023-08-15 22:19:48 +02:00
SChernykh 7630c1a883 CI: added msys2-clang Windows build 2023-08-15 19:53:22 +02:00
SChernykh 2877e5dfc1 Sync test: log stratum data when finished 2023-08-15 11:43:05 +02:00
SChernykh 05b88a48a3 CI: update to clang 17 2023-08-15 10:57:05 +02:00
SChernykh c74b567fe4 Update stratum_dummy.py 2023-08-15 08:00:11 +02:00
SChernykh a6b6cb0f09 TCPServer: tweaked ASAN support 2023-08-14 22:24:42 +02:00
SChernykh 86e9af6fd7 Sync test: submit more fake shares 2023-08-14 21:57:38 +02:00
SChernykh 8776f7dfbb Fixed MacOS sync test 2023-08-14 18:36:05 +02:00
SChernykh 929f908a86 Sync test: submit fake shares to test stratum 2023-08-14 17:10:36 +02:00
SChernykh 229d7b052a Create CONSOLE_COMMANDS.MD 2023-08-14 13:12:06 +02:00
SChernykh a5896f7ae8 Updated docs 2023-08-14 11:28:25 +02:00
SChernykh 114c2cee93 Updated dependencies
- cppzmq 4.10.0
- curl 8.2.1
- libuv 1.46
- latest libzmq
- latest miniupnp
- latest rapidjson
2023-08-13 21:05:39 +02:00
SChernykh 7f413ec994 Re-enabled CI jobs 2023-08-07 12:18:58 +02:00
SChernykh bd30a68e7d Fixed cppcheck error 2023-08-07 07:28:44 +02:00
SChernykh f4a18726b5 P2PServer: support future major protocol changes 2023-08-04 15:52:28 +02:00
SChernykh 50e284357c Disabled failing jobs 2023-08-01 16:16:56 +02:00
SChernykh 2ddb03e2be CI: tweaked memory leak output formatting 2023-07-19 16:15:48 +02:00
SChernykh ebae616138 CI: fixed error checking in sync test 2023-07-19 15:36:16 +02:00
SChernykh 0f88640575 CI: added sync test with memory leak detection 2023-07-19 13:59:57 +02:00
SChernykh 75cc82ae0c P2PServer: removed protocol version check for fastest peer 2023-07-12 12:48:52 +02:00
SChernykh 32dc235aa5 SideChain: fix for out of order blocks 2023-07-12 00:25:37 +02:00
SChernykh 6ffe1d81c2 P2PServer: ignore protocol versions higher than supported 2023-07-10 20:13:37 +02:00
SChernykh 5b245e64d3 Fixed a typo 2023-07-10 16:54:01 +02:00
SChernykh a067361d74 P2PServer: prefetch 2 blocks ahead during sync 2023-07-10 15:44:18 +02:00
SChernykh a7f66c8883 SideChain: filter duplicates from missing blocks 2023-07-10 14:11:22 +02:00
SChernykh e03e7d831e P2PServer: tweaked switching to the fastet peer when syncing 2023-07-10 11:40:48 +02:00
SChernykh 1219ed0dd6 P2PServer: check protocol version when choosing fastest peer 2023-07-07 23:49:43 +02:00
SChernykh fe2ff95f19 P2PServer: use BLOCK_NOTIFY to speed up syncing 2023-07-07 16:48:28 +02:00
SChernykh d72f0ce40c P2PServer: fixed some excess block requests 2023-07-07 14:52:47 +02:00
SChernykh df43e2c126 SideChain: tweaked precalc logic 2023-07-07 14:21:52 +02:00
SChernykh d8ecc1174d P2PServer: refactored BLOCK_NOTIFY logic
- Limit how many block requests can be in flight
- Don't send requests for the same block twice
2023-07-07 12:14:24 +02:00
SChernykh 3e269b49d4 Tweaked log level for BLOCK_NOTIFY 2023-07-05 19:06:49 +02:00
SChernykh 72c9f3b0db Fixed ping time calculation 2023-07-05 15:29:54 +02:00
SChernykh 2f5b0db786 P2PServer: request blocks coming from BLOCK_NOTIFY 2023-07-05 11:42:34 +02:00
SChernykh 8d9f16c387 P2PServer: sanity check message id 2023-07-04 16:47:14 +02:00
SChernykh d6cb0ee8a0 P2PServer: avoid unnecessary block broadcasts 2023-07-04 16:06:01 +02:00
SChernykh 5444701c38 Tweaked status code
Don't create stream when it's not needed
2023-07-02 15:33:51 +02:00
SChernykh 396479c2bf Fixed cppcheck errors 2023-07-02 13:10:05 +02:00
SChernykh d78885dcd4 p2pool v3.5
C/C++ CI / build-ubuntu (map[c:gcc-11 cpp:g++-11 os:ubuntu-20.04]) (push) Has been cancelled
C/C++ CI / build-ubuntu (map[c:gcc-12 cpp:g++-12 os:ubuntu-22.04]) (push) Has been cancelled
C/C++ CI / build-ubuntu-static-libs (push) Has been cancelled
C/C++ CI / build-ubuntu-aarch64 (map[os:ubuntu-20.04]) (push) Has been cancelled
C/C++ CI / build-ubuntu-aarch64 (map[os:ubuntu-22.04]) (push) Has been cancelled
C/C++ CI / build-windows-msys2 (push) Has been cancelled
C/C++ CI / build-windows-msbuild (map[msbuild:C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\amd64\ os:2019 rx:OFF upnp:OFF vs:Visual Studio 16 2019]) (push) Has been cancelled
C/C++ CI / build-windows-msbuild (map[msbuild:C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\amd64\ os:2019 rx:OFF upnp:ON vs:Visual Studio 16 2019]) (push) Has been cancelled
C/C++ CI / build-windows-msbuild (map[msbuild:C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\amd64\ os:2019 rx:ON upnp:ON vs:Visual Studio 16 2019]) (push) Has been cancelled
C/C++ CI / build-macos (macos-11) (push) Has been cancelled
C/C++ CI / build-macos (macos-12) (push) Has been cancelled
C/C++ CI / build-macos-aarch64 (macos-11) (push) Has been cancelled
C/C++ CI / build-macos-aarch64 (macos-12) (push) Has been cancelled
C/C++ CI / build-freebsd (map[architecture:x86-64 host:ubuntu-22.04 name:freebsd version:12.4]) (push) Has been cancelled
C/C++ CI / build-openbsd (map[architecture:x86-64 host:ubuntu-22.04 name:openbsd version:7.2]) (push) Has been cancelled
clang-tidy / clang-tidy (push) Has been cancelled
CodeQL / Analyze (cpp) (push) Has been cancelled
cppcheck / cppcheck-ubuntu (push) Has been cancelled
cppcheck / cppcheck-windows (push) Has been cancelled
Microsoft C++ Code Analysis / Analyze (push) Has been cancelled
Sync test / sync-test-ubuntu-tsan (push) Has been cancelled
Sync test / sync-test-ubuntu-msan (push) Has been cancelled
Sync test / sync-test-ubuntu-ubsan (push) Has been cancelled
Sync test / sync-test-ubuntu-asan (push) Has been cancelled
Sync test / sync-test-macos (push) Has been cancelled
Sync test / sync-test-windows-debug-asan (push) Has been cancelled
2023-06-30 18:05:12 +02:00
SChernykh ede72ff1d8 Suppress a noisy Coverity warning 2023-06-30 16:18:02 +02:00
SChernykh e5bf27030d Rate limit peer list requests
Send an empty response if the request comes too soon
2023-06-29 18:20:07 +02:00
SChernykh 375bf56e2e Fixed null characters in print_hosts output 2023-06-29 10:52:42 +02:00
SChernykh f79be1b343 Removed unnecessary lock 2023-06-27 17:09:58 +02:00
SChernykh 3554adf0c1 Refactored string conversions
Use `log::Stream` everywhere
2023-06-27 14:29:19 +02:00
SChernykh a32cc9f0f5 Update README.md 2023-06-22 17:21:45 +02:00
SChernykh 3759fd4ac4 Code cleanup 2023-06-22 09:26:05 +02:00
SChernykh ac58e8be2e Updated docs for multiple backup hosts 2023-06-21 11:29:13 +02:00
SChernykh 1c7646f98f ZMQReader: make sure monitor always shuts down 2023-06-20 16:53:03 +02:00
SChernykh 1b9d14e89d Get ping times for all hosts 2023-06-19 17:56:53 +02:00
SChernykh 3c41388eb7 Removed outdated hardfork information 2023-06-18 21:18:10 +02:00
SChernykh a9a2113ea4 Code cleanup 2023-06-18 16:47:31 +02:00
SChernykh b5fa34e1a1 Added support for multiple Monero hosts
Switch to the next host in list when P2Pool thinks current host is stuck or lagging
2023-06-18 12:56:27 +02:00
SChernykh 192f1d722d CI: tweaked cppcheck command line 2023-06-16 13:28:49 +02:00
SChernykh b857664d27 CI: skip external files for cppcheck 2023-06-16 11:08:01 +02:00
SChernykh 19491f0994 Update libcxx_msan.tar.xz 2023-06-15 15:22:52 +02:00
SChernykh 6738b57ba2 CI: use compile command database for cppcheck 2023-06-15 13:15:11 +02:00
SChernykh 30560e6cf8 CI: use compile command database for clang-tidy 2023-06-15 10:36:42 +02:00
SChernykh e1de021fba CI: tweaked cppcheck and clang-tidy command lines 2023-06-14 16:51:15 +02:00
SChernykh 8b4f05dc78 CI: added clang-tidy 2023-06-14 14:40:12 +02:00
SChernykh 950330b5f7 SideChain: recover from incorrect PoW calculation 2023-06-14 11:22:55 +02:00
SChernykh 9927718e25 Tweaked cppcheck command line 2023-06-13 11:53:41 +02:00
SChernykh b7ff4f2c2c Set default JSON parser flags 2023-06-12 15:29:23 +02:00
SChernykh 47c79459a6 Fixed get_miner_data error handling
Second call was a no-op because of `m_getMinerDataPending`
2023-06-10 14:49:33 +02:00
80 changed files with 1817 additions and 664 deletions
+209 -61
View File
@@ -1,8 +1,110 @@
name: C/C++ CI
on: [push, pull_request]
on:
push:
paths-ignore:
- 'docker-compose/**'
- 'docs/**'
- 'README.md'
pull_request:
jobs:
build-alpine-static:
timeout-minutes: 75
runs-on: ubuntu-22.04
strategy:
matrix:
config:
- {arch: x86_64, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline"}
- {arch: aarch64, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline"}
steps:
- name: Setup Alpine Linux
uses: jirutka/setup-alpine@v1
with:
arch: ${{ matrix.config.arch }}
- name: Install dependencies
shell: alpine.sh --root {0}
run: |
apk add git cmake gcc g++ make
- name: Checkout repository
uses: actions/checkout@v3
with:
submodules: true
- name: Build libcurl
shell: alpine.sh {0}
run: |
cd external/src/curl
cmake . -DCMAKE_C_FLAGS="-Os ${{ matrix.config.flags }}" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
make -j$(nproc)
cd lib && mkdir .libs && cp libcurl.a .libs
- name: Build libuv
shell: alpine.sh {0}
run: |
cd external/src/libuv
mkdir build
cd build
cmake .. -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
make -j$(nproc)
- name: Build libzmq
shell: alpine.sh {0}
run: |
cd external/src/libzmq
mkdir build
cd build
cmake .. -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DCMAKE_CXX_FLAGS='-Os ${{ matrix.config.flags }}' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
make -j$(nproc)
- name: Build p2pool
shell: alpine.sh {0}
run: |
mkdir build
cd build
cmake .. -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_BINARY=ON
make -j$(nproc)
- name: Run RandomX tests
shell: alpine.sh {0}
run: |
build/p2pool --test
build/external/src/RandomX/randomx-tests
- name: Build tests
shell: alpine.sh {0}
run: |
cd tests
mkdir build
cd build
cmake .. -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON
make -j$(nproc)
- name: Run tests
shell: alpine.sh {0}
run: |
cd tests/build
gunzip *.gz
./p2pool_tests
- name: List directory
run: |
cd build
ls -la
file p2pool
- name: Archive binary
uses: actions/upload-artifact@v3
with:
name: p2pool-alpine-static-${{ matrix.config.arch }}
path: build/p2pool
build-ubuntu:
timeout-minutes: 10
@@ -30,15 +132,20 @@ jobs:
run: |
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }}
cmake .. -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }} -DCMAKE_C_FLAGS='-flto=2' -DCMAKE_CXX_FLAGS='-flto=2'
make -j$(nproc)
- name: Run RandomX tests
run: |
build/p2pool --test
build/external/src/RandomX/randomx-tests
- name: Build tests
run: |
cd tests
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }}
cmake .. -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }} -DCMAKE_C_FLAGS='-flto=2' -DCMAKE_CXX_FLAGS='-flto=2'
make -j$(nproc)
- name: Run tests
@@ -58,6 +165,11 @@ jobs:
timeout-minutes: 15
runs-on: ubuntu-22.04
strategy:
matrix:
config:
- {flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline"}
steps:
- name: Install dependencies
run: |
@@ -74,7 +186,7 @@ jobs:
- name: Build libcurl
run: |
cd external/src/curl
cmake . -DCMAKE_C_FLAGS="-Os" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
cmake . -DCMAKE_C_FLAGS="-Os ${{ matrix.config.flags }}" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
make -j$(nproc)
cd lib && mkdir .libs && cp libcurl.a .libs
@@ -83,7 +195,7 @@ jobs:
cd external/src/libuv
mkdir build
cd build
cmake .. -DCMAKE_C_FLAGS='-Os' -DBUILD_TESTING=OFF
cmake .. -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
make -j$(nproc)
- name: Build libzmq
@@ -91,22 +203,27 @@ jobs:
cd external/src/libzmq
mkdir build
cd build
cmake .. -DCMAKE_C_FLAGS='-Os' -DCMAKE_CXX_FLAGS='-Os' -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DWITH_PERF_TOOL=OFF
cmake .. -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DCMAKE_CXX_FLAGS='-Os ${{ matrix.config.flags }}' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
make -j$(nproc)
- name: Build p2pool
run: |
mkdir build
cd build
cmake .. -DSTATIC_LIBS=ON
cmake .. -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON
make -j$(nproc)
- name: Run RandomX tests
run: |
build/p2pool --test
build/external/src/RandomX/randomx-tests
- name: Build tests
run: |
cd tests
mkdir build
cd build
cmake .. -DSTATIC_LIBS=ON
cmake .. -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON
make -j$(nproc)
- name: Run tests
@@ -123,20 +240,20 @@ jobs:
build-ubuntu-aarch64:
timeout-minutes: 10
timeout-minutes: 15
runs-on: ${{ matrix.config.os }}
strategy:
matrix:
config:
- {os: ubuntu-20.04}
- {os: ubuntu-22.04}
- {os: ubuntu-20.04, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections"}
- {os: ubuntu-22.04, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections"}
steps:
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y git build-essential cmake gcc-aarch64-linux-gnu g++-aarch64-linux-gnu binutils-aarch64-linux-gnu
sudo apt install -y git build-essential cmake gcc-aarch64-linux-gnu g++-aarch64-linux-gnu binutils-aarch64-linux-gnu qemu-user
- name: Checkout repository
uses: actions/checkout@v3
@@ -146,7 +263,7 @@ jobs:
- name: Build libcurl
run: |
cd external/src/curl
cmake . -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_C_FLAGS="-Os" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
cmake . -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_C_FLAGS="-Os ${{ matrix.config.flags }}" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
make -j$(nproc)
cd lib && mkdir .libs && cp libcurl.a .libs
@@ -155,7 +272,7 @@ jobs:
cd external/src/libuv
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_C_FLAGS='-Os' -DBUILD_TESTING=OFF
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
make -j$(nproc)
- name: Build libzmq
@@ -163,16 +280,35 @@ jobs:
cd external/src/libzmq
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_C_FLAGS='-Os' -DCMAKE_CXX_FLAGS='-Os' -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DWITH_PERF_TOOL=OFF
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DCMAKE_CXX_FLAGS='-Os ${{ matrix.config.flags }}' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
make -j$(nproc)
- name: Build p2pool
run: |
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_STRIP=/usr/bin/aarch64-linux-gnu-strip -DSTATIC_LIBS=ON -DARCH_ID=aarch64
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_STRIP=/usr/bin/aarch64-linux-gnu-strip -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON -DARCH_ID=aarch64
make -j$(nproc)
- name: Run RandomX tests
run: |
qemu-aarch64 -L /usr/aarch64-linux-gnu build/p2pool --test
qemu-aarch64 -L /usr/aarch64-linux-gnu build/external/src/RandomX/randomx-tests
- name: Build tests
run: |
cd tests
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_STRIP=/usr/bin/aarch64-linux-gnu-strip -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON -DARCH_ID=aarch64
make -j$(nproc)
- name: Run tests
run: |
cd tests/build
gunzip *.gz
qemu-aarch64 -L /usr/aarch64-linux-gnu ./p2pool_tests
- name: Archive binary
uses: actions/upload-artifact@v3
with:
@@ -184,6 +320,12 @@ jobs:
timeout-minutes: 45
runs-on: windows-latest
strategy:
matrix:
config:
- {c: "gcc", cxx: "g++", flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=maybe-uninitialized -Wno-error=attributes"}
- {c: "clang", cxx: "clang++", flags: "-flto -ffunction-sections -fuse-ld=lld -Wno-unused-command-line-argument"}
defaults:
run:
shell: msys2 {0}
@@ -198,12 +340,12 @@ jobs:
uses: eine/setup-msys2@v2
with:
update: true
install: mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake make
install: mingw-w64-x86_64-toolchain mingw-w64-x86_64-clang mingw-w64-x86_64-lld mingw-w64-x86_64-cmake make
- name: Build libcurl
run: |
cd external/src/curl
cmake . -G "Unix Makefiles" -DCMAKE_C_FLAGS="-Os" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
cmake . -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_C_FLAGS="-Os ${{ matrix.config.flags }}" -DCURL_TARGET_WINDOWS_VERSION=0x0600 -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
make -j$(nproc)
cd lib && mkdir .libs && cp libcurl.a .libs
@@ -212,7 +354,7 @@ jobs:
cd external/src/libuv
mkdir build
cd build
cmake .. -G "Unix Makefiles" -DCMAKE_C_FLAGS='-Os' -DBUILD_TESTING=OFF
cmake .. -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
make -j$(nproc)
- name: Build libzmq
@@ -220,22 +362,27 @@ jobs:
cd external/src/libzmq
mkdir build
cd build
cmake .. -G "Unix Makefiles" -DCMAKE_C_FLAGS='-Os' -DCMAKE_CXX_FLAGS='-Os' -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DZMQ_HAVE_IPC=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DWITH_PERF_TOOL=OFF
cmake .. -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cxx }} -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DCMAKE_CXX_FLAGS='-Os ${{ matrix.config.flags }}' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DZMQ_HAVE_IPC=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
make -j$(nproc)
- name: Build p2pool
run: |
mkdir build
cd build
cmake .. -G "Unix Makefiles" -DSTATIC_LIBS=ON
cmake .. -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cxx }} -DCMAKE_C_FLAGS="${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections" -DCMAKE_CXX_FLAGS="${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections" -DSTATIC_LIBS=ON
make -j$(nproc)
- name: Run RandomX tests
run: |
build/p2pool.exe --test
build/external/src/RandomX/randomx-tests.exe
- name: Build tests
run: |
cd tests
mkdir build
cd build
cmake .. -G "Unix Makefiles" -DSTATIC_LIBS=ON
cmake .. -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cxx }} -DCMAKE_C_FLAGS="${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections" -DCMAKE_CXX_FLAGS="${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections" -DSTATIC_LIBS=ON
make -j$(nproc)
- name: Run tests
@@ -247,7 +394,7 @@ jobs:
- name: Archive binary
uses: actions/upload-artifact@v3
with:
name: p2pool-msys2.exe
name: p2pool-msys2-${{ matrix.config.c }}.exe
path: build/p2pool.exe
build-windows-msbuild:
@@ -276,7 +423,15 @@ jobs:
mkdir build
cd build
cmake .. -G "${{ matrix.config.vs }}" -DWITH_RANDOMX=${{ matrix.config.rx }} -DWITH_UPNP=${{ matrix.config.upnp }}
& "${{ matrix.config.msbuild }}msbuild" /m /p:Configuration=Release p2pool.vcxproj
& "${{ matrix.config.msbuild }}msbuild" -v:m /m /p:Configuration=Release p2pool.vcxproj
- name: Run RandomX tests
if: matrix.config.rx == 'ON'
run: |
build/Release/p2pool.exe --test
cd build/external/src/RandomX
& "${{ matrix.config.msbuild }}msbuild" -v:m /m /p:Configuration=Release randomx-tests.vcxproj
Release/randomx-tests.exe
- name: Build tests
run: |
@@ -284,7 +439,7 @@ jobs:
mkdir build
cd build
cmake .. -G "${{ matrix.config.vs }}"
& "${{ matrix.config.msbuild }}msbuild" /m /p:Configuration=Debug p2pool_tests.vcxproj
& "${{ matrix.config.msbuild }}msbuild" -v:m /m /p:Configuration=Debug p2pool_tests.vcxproj
- name: Run tests
run: |
@@ -300,12 +455,8 @@ jobs:
build-macos:
timeout-minutes: 15
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-11, macos-12]
timeout-minutes: 20
runs-on: macos-11
steps:
- name: Checkout repository
@@ -313,13 +464,10 @@ jobs:
with:
submodules: recursive
- name: Install dependencies
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake
- name: Build libcurl
run: |
cd external/src/curl
cmake . -DCMAKE_C_FLAGS="-Os" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
cmake . -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-Os -flto" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
make -j3
cd lib && mkdir .libs && cp libcurl.a .libs
@@ -328,7 +476,7 @@ jobs:
cd external/src/libuv
mkdir build
cd build
cmake .. -DCMAKE_C_FLAGS='-Os' -DBUILD_TESTING=OFF
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-Os -flto' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
make -j3
- name: Build libzmq
@@ -336,22 +484,27 @@ jobs:
cd external/src/libzmq
mkdir build
cd build
cmake .. -DCMAKE_C_FLAGS='-Os' -DCMAKE_CXX_FLAGS='-Os' -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DWITH_PERF_TOOL=OFF
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-Os -flto' -DCMAKE_CXX_FLAGS='-Os -flto' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
make -j3
- name: Build p2pool
run: |
mkdir build
cd build
cmake .. -DSTATIC_BINARY=ON
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-flto" -DCMAKE_CXX_FLAGS="-flto" -DSTATIC_LIBS=ON
make -j3
- name: Run RandomX tests
run: |
build/p2pool --test
build/external/src/RandomX/randomx-tests
- name: Build tests
run: |
cd tests
mkdir build
cd build
cmake .. -DSTATIC_LIBS=ON
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-flto" -DCMAKE_CXX_FLAGS="-flto" -DSTATIC_LIBS=ON
make -j3
- name: Run tests
@@ -363,17 +516,13 @@ jobs:
- name: Archive binary
uses: actions/upload-artifact@v3
with:
name: p2pool-${{ matrix.os }}
name: p2pool-macos-11
path: build/p2pool
build-macos-aarch64:
timeout-minutes: 15
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-11, macos-12]
timeout-minutes: 20
runs-on: macos-11
steps:
- name: Checkout repository
@@ -381,13 +530,10 @@ jobs:
with:
submodules: recursive
- name: Install dependencies
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake
- name: Build libcurl
run: |
cd external/src/curl
cmake . -DCMAKE_C_FLAGS='-Os -target arm64-apple-${{ matrix.os }}' -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
cmake . -DCMAKE_C_FLAGS="-Os -flto -target arm64-apple-macos-11" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
make -j3
cd lib && mkdir .libs && cp libcurl.a .libs
@@ -396,7 +542,7 @@ jobs:
cd external/src/libuv
mkdir build
cd build
cmake .. -DCMAKE_C_FLAGS='-Os -target arm64-apple-${{ matrix.os }}' -DBUILD_TESTING=OFF
cmake .. -DCMAKE_C_FLAGS='-Os -flto -target arm64-apple-macos-11' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
make -j3
- name: Build libzmq
@@ -404,20 +550,20 @@ jobs:
cd external/src/libzmq
mkdir build
cd build
cmake .. -DCMAKE_C_FLAGS='-Os -target arm64-apple-${{ matrix.os }}' -DCMAKE_CXX_FLAGS='-Os -target arm64-apple-${{ matrix.os }}' -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DWITH_PERF_TOOL=OFF
cmake .. -DCMAKE_C_FLAGS='-Os -flto -target arm64-apple-macos-11' -DCMAKE_CXX_FLAGS='-Os -flto -target arm64-apple-macos-11' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
make -j3
- name: Build p2pool
run: |
mkdir build
cd build
cmake .. -DCMAKE_C_FLAGS='-target arm64-apple-${{ matrix.os }}' -DCMAKE_CXX_FLAGS='-target arm64-apple-${{ matrix.os }}' -DSTATIC_BINARY=ON -DARCH_ID=aarch64
cmake .. -DCMAKE_C_FLAGS="-flto -target arm64-apple-macos-11" -DCMAKE_CXX_FLAGS="-flto -target arm64-apple-macos-11" -DSTATIC_LIBS=ON -DARCH_ID=aarch64
make -j3
- name: Archive binary
uses: actions/upload-artifact@v3
with:
name: p2pool-${{ matrix.os }}-aarch64
name: p2pool-macos-11-aarch64
path: build/p2pool
build-freebsd:
@@ -440,7 +586,7 @@ jobs:
submodules: recursive
- name: Build p2pool
uses: cross-platform-actions/action@v0.10.0
uses: cross-platform-actions/action@v0.19.0
with:
operating_system: ${{ matrix.os.name }}
architecture: ${{ matrix.os.architecture }}
@@ -449,28 +595,30 @@ jobs:
run: |
sudo pkg install -y cmake
cd external/src/curl
cmake . -DCMAKE_C_FLAGS="-Os" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
cmake . -DCMAKE_C_FLAGS="-Os -flto" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
make -j2
cd lib && mkdir .libs && cp libcurl.a .libs
cd ../../libuv
mkdir build
cd build
cmake .. -DCMAKE_C_FLAGS='-Os' -DBUILD_TESTING=OFF
cmake .. -DCMAKE_C_FLAGS='-Os -flto' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
make -j2
cd ../../libzmq
mkdir build
cd build
cmake .. -DCMAKE_C_FLAGS='-Os' -DCMAKE_CXX_FLAGS='-Os' -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DWITH_PERF_TOOL=OFF
cmake .. -DCMAKE_C_FLAGS='-Os -flto' -DCMAKE_CXX_FLAGS='-Os -flto' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
make -j2
cd ../../../..
mkdir build
cd build
cmake .. -DSTATIC_BINARY=ON
cmake .. -DCMAKE_C_FLAGS='-flto' -DCMAKE_CXX_FLAGS='-flto' -DSTATIC_LIBS=ON
make -j2
./p2pool --test
external/src/RandomX/randomx-tests
cd ../tests
mkdir build
cd build
cmake .. -DSTATIC_LIBS=ON
cmake .. -DCMAKE_C_FLAGS='-flto' -DCMAKE_CXX_FLAGS='-flto' -DSTATIC_LIBS=ON
make -j2
gunzip *.gz
./p2pool_tests
@@ -501,7 +649,7 @@ jobs:
submodules: recursive
- name: Build p2pool
uses: cross-platform-actions/action@v0.10.0
uses: cross-platform-actions/action@v0.19.0
with:
operating_system: ${{ matrix.os.name }}
architecture: ${{ matrix.os.architecture }}
+44
View File
@@ -0,0 +1,44 @@
name: clang-tidy
on:
push:
paths-ignore:
- 'docker-compose/**'
- 'docs/**'
- 'README.md'
pull_request:
jobs:
clang-tidy:
runs-on: ubuntu-22.04
steps:
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y libuv1-dev libzmq3-dev libcurl4-openssl-dev
- name: Install clang
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 17
sudo apt-get install -y clang-tidy-17
clang-tidy-17 --verify-config
- name: Checkout repository
uses: actions/checkout@v3
with:
submodules: true
- name: cmake p2pool
run: |
mkdir build
cd build
cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DDEV_CLANG_TIDY=ON
- name: Run clang-tidy
run: |
cd src
clang-tidy-17 *.cpp -p ../build -checks=-clang-diagnostic-undefined-internal -warnings-as-errors=* -header-filter=^[^\.]
+6
View File
@@ -13,7 +13,13 @@ name: "CodeQL"
on:
push:
paths-ignore:
- 'docker-compose/**'
- 'docs/**'
- 'README.md'
pull_request:
schedule:
- cron: '44 11 * * 0'
+33 -3
View File
@@ -2,17 +2,28 @@ name: cppcheck
on:
push:
paths-ignore:
- 'docker-compose/**'
- 'docs/**'
- 'README.md'
pull_request:
schedule:
- cron: '57 0 * * *'
jobs:
cppcheck-ubuntu:
timeout-minutes: 30
timeout-minutes: 50
runs-on: ubuntu-latest
steps:
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y libuv1-dev libzmq3-dev libcurl4-openssl-dev
- name: Checkout repository
uses: actions/checkout@v3
with:
@@ -29,14 +40,27 @@ jobs:
cd cppcheck-main
make -j$(nproc) cppcheck
- name: cmake p2pool
run: |
mkdir build
cd build
cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DSTATIC_LIBS=ON
python ../cppcheck/remove_external.py compile_commands.json
- name: Run cppcheck
run: |
cd cppcheck
./run.sh
- name: Archive full error list
uses: actions/upload-artifact@v3
with:
name: errors_full-linux
path: cppcheck/errors_full.txt
cppcheck-windows:
timeout-minutes: 20
timeout-minutes: 50
runs-on: windows-latest
steps:
@@ -63,9 +87,15 @@ jobs:
run: |
mkdir build
cd build
cmake .. -G "Visual Studio 17 2022"
cmake .. -G "Visual Studio 17 2022" -DSTATIC_LIBS=ON
- name: Run cppcheck
run: |
cd cppcheck
./run.cmd
- name: Archive full error list
uses: actions/upload-artifact@v3
with:
name: errors_full-windows
path: cppcheck/errors_full.txt
-36
View File
@@ -1,36 +0,0 @@
name: Build libc++ for MemorySanitizer
on: [workflow_dispatch]
jobs:
build-libcxx_msan:
runs-on: ubuntu-22.04
steps:
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y git cmake ninja-build
- name: Install clang
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 16
- name: Build libcxx_msan
run: |
git clone --depth=1 https://github.com/llvm/llvm-project -b release/16.x
cd llvm-project
mkdir build
cmake -G Ninja -S runtimes -B build -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" -DCMAKE_C_COMPILER=clang-16 -DCMAKE_CXX_COMPILER=clang++-16 -DLLVM_USE_SANITIZER=MemoryWithOrigins
ninja -C build cxx cxxabi
cd build
XZ_OPT=-e9 tar cfJ libcxx_msan.tar.xz include lib
- name: Archive libcxx_msan.tar.xz
uses: actions/upload-artifact@v3
with:
name: libcxx_msan
path: llvm-project/build/libcxx_msan.tar.xz
+6
View File
@@ -10,7 +10,13 @@ name: Microsoft C++ Code Analysis
on:
push:
paths-ignore:
- 'docker-compose/**'
- 'docs/**'
- 'README.md'
pull_request:
schedule:
- cron: '40 10 * * 0'
+24
View File
@@ -0,0 +1,24 @@
name: source-snapshot
on: [push, pull_request]
jobs:
source-snapshot:
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
submodules: true
- name: Compress source code
run: |
mkdir build
XZ_OPT=-e9 tar --exclude=".git" --exclude="build" -f build/p2pool_source.tar.xz -c ../p2pool --xz
- name: Archive source code
uses: actions/upload-artifact@v3
with:
name: p2pool_source.tar.xz
path: build/p2pool_source.tar.xz
+108 -35
View File
@@ -2,7 +2,13 @@ name: Sync test
on:
push:
paths-ignore:
- 'docker-compose/**'
- 'docs/**'
- 'README.md'
pull_request:
schedule:
- cron: '17 0/3 * * *'
@@ -28,18 +34,21 @@ jobs:
run: |
mkdir build
cd build
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_TSAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_TSAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_C_FLAGS="-flto=2" -DCMAKE_CXX_FLAGS="-flto=2"
make -j$(nproc)
- name: Run p2pool
timeout-minutes: 25
run: |
cd build
mkdir data
python ../tests/src/stratum_dummy.py 1 &
python ../tests/src/stratum_dummy.py 2 &
python ../tests/src/stratum_dummy.py 3 &
TSAN_OPTIONS="suppressions=../tests/src/tsan_sup.txt halt_on_error=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
TSAN_OPTIONS="suppressions=../tests/src/tsan_sup.txt halt_on_error=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
- name: Check p2pool.log
run: |
cd build
grep 'Synchronization finished successfully' p2pool.log
- name: Archive p2pool.log
@@ -51,7 +60,6 @@ jobs:
build/data/
sync-test-ubuntu-msan:
timeout-minutes: 30
runs-on: ubuntu-22.04
@@ -59,30 +67,35 @@ jobs:
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y git build-essential cmake libuv1-dev libzmq3-dev libsodium-dev libpgm-dev libnorm-dev libgss-dev libcurl4-openssl-dev libidn2-0-dev
sudo apt install -y git build-essential cmake ninja-build
- name: Install clang
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 16
sudo ./llvm.sh 17
- name: Build libcxx_msan
run: |
git clone --depth=1 https://github.com/llvm/llvm-project -b release/17.x
cd llvm-project
mkdir build
cmake -G Ninja -S runtimes -B build -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DLLVM_USE_SANITIZER=MemoryWithOrigins
ninja -C build cxx cxxabi
cd build
mkdir /tmp/libcxx_msan
cp -r include /tmp/libcxx_msan
cp -r lib /tmp/libcxx_msan
- name: Checkout repository
uses: actions/checkout@v3
with:
submodules: true
- name: Install libcxx_msan
run: |
mkdir /tmp/libcxx_msan
cp tests/src/libcxx_msan.tar.xz /tmp/libcxx_msan
cd /tmp/libcxx_msan
tar xvf libcxx_msan.tar.xz
- name: Build libcurl
run: |
cd external/src/curl
cmake . -DCMAKE_C_COMPILER=clang-16 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g' -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
cmake . -DCMAKE_C_COMPILER=clang-17 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g' -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
make -j$(nproc)
cd lib && mkdir .libs && cp libcurl.a .libs
@@ -91,7 +104,7 @@ jobs:
cd external/src/libuv
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=clang-16 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g' -DBUILD_TESTING=OFF
cmake .. -DCMAKE_C_COMPILER=clang-17 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
make -j$(nproc)
- name: Build libzmq
@@ -99,25 +112,28 @@ jobs:
cd external/src/libzmq
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=clang-16 -DCMAKE_CXX_COMPILER=clang++-16 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g' -DCMAKE_CXX_FLAGS='-nostdinc++ -nostdlib++ -fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g -isystem /tmp/libcxx_msan/include/c++/v1 -L/tmp/libcxx_msan/lib -lc++ -lc++abi -Wno-unused-command-line-argument' -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DWITH_PERF_TOOL=OFF
cmake .. -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g' -DCMAKE_CXX_FLAGS='-nostdinc++ -nostdlib++ -fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g -isystem /tmp/libcxx_msan/include/c++/v1 -L/tmp/libcxx_msan/lib -lc++ -lc++abi -Wno-unused-command-line-argument' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
make -j$(nproc)
- name: Build p2pool
run: |
mkdir build
cd build
cmake .. -DCMAKE_C_COMPILER=clang-16 -DCMAKE_CXX_COMPILER=clang++-16 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -fno-omit-frame-pointer -g' -DCMAKE_CXX_FLAGS='-nostdinc++ -nostdlib++ -fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -isystem /tmp/libcxx_msan/include/c++/v1 -L/tmp/libcxx_msan/lib -Wl,-rpath /tmp/libcxx_msan/lib -lc++ -lc++abi -Wno-unused-command-line-argument -fuse-ld=lld-16 -fno-omit-frame-pointer -g' -DDEV_TEST_SYNC=ON -DDEV_WITH_MSAN=ON -DSTATIC_LIBS=ON
cmake .. -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -fno-omit-frame-pointer -g' -DCMAKE_CXX_FLAGS='-nostdinc++ -nostdlib++ -fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -isystem /tmp/libcxx_msan/include/c++/v1 -L/tmp/libcxx_msan/lib -Wl,-rpath /tmp/libcxx_msan/lib -lc++ -lc++abi -Wno-unused-command-line-argument -fuse-ld=lld-17 -fno-omit-frame-pointer -g' -DDEV_TEST_SYNC=ON -DDEV_WITH_MSAN=ON -DSTATIC_LIBS=ON
make -j$(nproc)
- name: Run p2pool
timeout-minutes: 20
run: |
cd build
mkdir data
python ../tests/src/stratum_dummy.py 1 &
python ../tests/src/stratum_dummy.py 2 &
python ../tests/src/stratum_dummy.py 3 &
MSAN_OPTIONS="halt_on_error=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
MSAN_OPTIONS="halt_on_error=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
- name: Check p2pool.log
run: |
cd build
grep 'Synchronization finished successfully' p2pool.log
- name: Archive p2pool.log
@@ -149,18 +165,21 @@ jobs:
run: |
mkdir build
cd build
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_UBSAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_UBSAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_C_FLAGS="-flto=2" -DCMAKE_CXX_FLAGS="-flto=2"
make -j$(nproc)
- name: Run p2pool
timeout-minutes: 20
run: |
cd build
mkdir data
python ../tests/src/stratum_dummy.py 1 &
python ../tests/src/stratum_dummy.py 2 &
python ../tests/src/stratum_dummy.py 3 &
UBSAN_OPTIONS="suppressions=../tests/src/ubsan_sup.txt halt_on_error=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
UBSAN_OPTIONS="suppressions=../tests/src/ubsan_sup.txt halt_on_error=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
- name: Check p2pool.log
run: |
cd build
grep 'Synchronization finished successfully' p2pool.log
- name: Archive p2pool.log
@@ -192,18 +211,21 @@ jobs:
run: |
mkdir build
cd build
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_ASAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_ASAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_C_FLAGS="-flto=2" -DCMAKE_CXX_FLAGS="-flto=2"
make -j$(nproc)
- name: Run p2pool
timeout-minutes: 20
run: |
cd build
mkdir data
python ../tests/src/stratum_dummy.py 1 &
python ../tests/src/stratum_dummy.py 2 &
python ../tests/src/stratum_dummy.py 3 &
ASAN_OPTIONS="detect_stack_use_after_return=1 atexit=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
ASAN_OPTIONS="detect_stack_use_after_return=1 atexit=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
- name: Check p2pool.log
run: |
cd build
grep 'Synchronization finished successfully' p2pool.log
- name: Archive p2pool.log
@@ -217,7 +239,7 @@ jobs:
sync-test-macos:
timeout-minutes: 30
runs-on: macos-12
runs-on: macos-13
steps:
- name: Checkout repository
@@ -226,7 +248,9 @@ jobs:
submodules: recursive
- name: Install dependencies
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake libuv zmq libpgm curl
run: |
HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake libuv zmq libpgm curl pyenv
pyenv install 3:latest
- name: Build p2pool
run: |
@@ -236,14 +260,17 @@ jobs:
make -j3
- name: Run p2pool
timeout-minutes: 20
run: |
cd build
mkdir data
python ../tests/src/stratum_dummy.py 1 &
python ../tests/src/stratum_dummy.py 2 &
python ../tests/src/stratum_dummy.py 3 &
./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
python3 ../tests/src/stratum_dummy.py 1 &
python3 ../tests/src/stratum_dummy.py 2 &
python3 ../tests/src/stratum_dummy.py 3 &
./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
- name: Check p2pool.log
run: |
cd build
grep 'Synchronization finished successfully' p2pool.log
- name: Archive p2pool.log
@@ -273,17 +300,20 @@ jobs:
mkdir build
cd build
cmake .. -G "Visual Studio 17 2022" -DDEV_TEST_SYNC=ON
& "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\msbuild" /m /p:Configuration=Debug p2pool.vcxproj
& "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\msbuild" -v:m /m /p:Configuration=Debug p2pool.vcxproj
- name: Run p2pool
timeout-minutes: 20
run: |
cd build/Debug
mkdir data
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 1"
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 2"
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 3"
./p2pool.exe --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
./p2pool.exe --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
- name: Check p2pool.log
run: |
cd build/Debug
findstr /C:"Synchronization finished successfully" p2pool.log
- name: Archive p2pool.log
@@ -293,3 +323,46 @@ jobs:
path: |
build/Debug/*.log
build/Debug/data/
sync-test-windows-leaks:
timeout-minutes: 30
runs-on: windows-2022
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
submodules: recursive
- name: Setup cmake
uses: lukka/get-cmake@latest
- name: Build p2pool
run: |
mkdir build
cd build
cmake .. -G "Visual Studio 17 2022" -DDEV_TEST_SYNC=ON -DDEV_TRACK_MEMORY=ON
& "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\msbuild" -v:m /m /p:Configuration=RelWithDebInfo p2pool.vcxproj
- name: Run p2pool
run: |
cd build/RelWithDebInfo
mkdir data
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 1"
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 2"
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 3"
./p2pool.exe --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
- name: Check p2pool.log
run: |
cd build/RelWithDebInfo
findstr /C:"Synchronization finished successfully" p2pool.log
- name: Archive p2pool.log
uses: actions/upload-artifact@v3
with:
name: p2pool_windows_data_leaks
path: |
build/RelWithDebInfo/*.log
build/RelWithDebInfo/data/
+19 -3
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.12)
cmake_minimum_required(VERSION 3.5)
project(p2pool)
option(STATIC_BINARY "Build static binary" OFF)
@@ -12,6 +12,8 @@ option(DEV_WITH_TSAN "[Developer only] Compile with thread sanitizer" OFF)
option(DEV_WITH_MSAN "[Developer only] Compile with memory sanitizer" OFF)
option(DEV_WITH_UBSAN "[Developer only] Compile with undefined behavior sanitizer" OFF)
option(DEV_WITH_ASAN "[Developer only] Compile with address sanitizer" OFF)
option(DEV_CLANG_TIDY "[Developer only] Compile for clang-tidy" OFF)
option(DEV_TRACK_MEMORY "[Developer only] Track memory allocations" OFF)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
@@ -51,6 +53,14 @@ if (DEV_WITH_ASAN)
add_definitions(-DDEV_WITH_ASAN)
endif()
if (DEV_CLANG_TIDY)
add_definitions(-DDEV_CLANG_TIDY)
endif()
if (DEV_TRACK_MEMORY)
add_definitions(-DDEV_TRACK_MEMORY)
endif()
include(cmake/flags.cmake)
set(HEADERS
@@ -115,7 +125,7 @@ if (WITH_RANDOMX)
set(SOURCES ${SOURCES} src/miner.cpp)
endif()
if (NOT STATIC_BINARY AND NOT STATIC_LIBS)
if (NOT ((CMAKE_CXX_COMPILER_ID MATCHES MSVC) OR STATIC_BINARY OR STATIC_LIBS))
include(FindCURL)
endif()
@@ -154,6 +164,8 @@ if (WIN32)
set(LIBS ${LIBS} bcrypt)
endif()
add_definitions(-DCURL_STATICLIB)
add_definitions(-DWIN32_LEAN_AND_MEAN)
add_definitions(-D_WIN32_WINNT=0x0600)
elseif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
set(LIBS ${LIBS} pthread)
elseif (NOT APPLE)
@@ -295,6 +307,8 @@ if (HAVE_RES_QUERY)
endif()
endif()
add_definitions("-DRAPIDJSON_PARSE_DEFAULT_FLAGS=kParseTrailingCommasFlag")
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES})
if (STATIC_BINARY OR STATIC_LIBS)
@@ -306,6 +320,8 @@ if (STATIC_BINARY OR STATIC_LIBS)
endif()
endif()
set(STATIC_LIBS "")
if (WITH_RANDOMX)
set(STATIC_LIBS randomx)
endif()
@@ -316,7 +332,7 @@ if (STATIC_BINARY OR STATIC_LIBS)
if (WIN32)
set(STATIC_LIBS ${STATIC_LIBS} ws2_32 iphlpapi userenv psapi dnsapi dbghelp)
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
if ((CMAKE_CXX_COMPILER_ID MATCHES GNU) OR (CMAKE_CXX_COMPILER_ID MATCHES Clang))
set(STATIC_LIBS ${STATIC_LIBS} bcrypt)
endif()
elseif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
+21 -22
View File
@@ -6,12 +6,6 @@ Pool status and monitoring pages can be found at https://p2pool.io/, https://p2p
These are 3rd-party pages. If they are down, it doesn't mean there is a problem with P2Pool itself - it keeps mining always thanks to its decentralized nature.
# P2Pool hardforked on March 18, 2023
P2Pool (not Monero!) hardforked to new consensus rules on March 18th at 21:00 UTC. The hardfork was necessary to improve P2Pool scalability and reduce the impact on Monero blockchain. You need to update to the latest P2Pool version to continue mining on P2Pool.
Reddit discussions: [original announcement](https://www.reddit.com/r/MoneroMining/comments/1095730/psa_p2pool_network_upgrade_aka_hardfork_on_march/), [final announcement](https://www.reddit.com/r/MoneroMining/comments/11tln6z/psa_p2pool_miners_update_to_the_latest_version/)
### Build Status
![C/C++ CI](https://github.com/SChernykh/p2pool/actions/workflows/c-cpp.yml/badge.svg)
@@ -24,10 +18,11 @@ Reddit discussions: [original announcement](https://www.reddit.com/r/MoneroMinin
<img alt="Coverity Scan Build Status"
src="https://scan.coverity.com/projects/23659/badge.svg"/>
</a>
![clang-tidy](https://github.com/SChernykh/p2pool/actions/workflows/clang-tidy.yml/badge.svg)
# Contents
- [Pool mining vs Solo mining vs P2Pool mining](#pool-mining-vs-solo-mining-vs-p2pool-mining)
- [Features](#features)
- [How PPLNS works in P2Pool](#how-pplns-works-in-p2pool)
- [How payouts work in P2Pool](#how-payouts-work-in-p2pool)
- [Default P2Pool parameters](#default-p2pool-parameters)
- [Monero version support](#monero-version-support)
- [How to mine on P2Pool](#how-to-mine-on-p2pool)
@@ -46,7 +41,7 @@ Here's the comparison table of the different ways of mining. While pool mining i
|-|-|-|-|-|-|-|-|
|Centralized pool|Regular|0-3%|0.001-0.01 XMR|Yes|Less stable due to pool server outages|Pool admin controls your mined funds, what you mine and can execute network attacks|Only miner software is required
|Solo|Rare|0%|0.6 XMR or more|No|As stable as your Monero node|100% under your control|Monero node + optional miner
|**P2Pool**|Regular|0%|~0.0003 XMR|No|As stable as your Monero node|100% under your control|Monero node + P2Pool node + miner
|**P2Pool**|Regular|0%|~0.00027 XMR|No|Very stable: node failover and multiple Monero nodes are supported|100% under your control|Monero node(s) + P2Pool node(s) + optional miner(s)
## Features
@@ -56,28 +51,32 @@ Here's the comparison table of the different ways of mining. While pool mining i
* PPLNS payout scheme
* **0% fee**
* **0 XMR payout fee**
* **~0.0003 XMR minimal payout**
* **~0.00027 XMR minimal payout**
* Fast block times, down to 1 second
* Uncle blocks are supported to avoid orphans - all your shares will be accounted for!
* Configurable PPLNS window size and block time
* Advanced mempool picking algorithm, it creates blocks with better reward than what monerod solo mining does
* Password protected private pools
* Highly reliable configurations are supported (multiple P2Pool nodes mining to the same wallet, each P2Pool node can use multiple Monero nodes and switch on the fly if an issue is detected)
## How PPLNS works in P2Pool
## How payouts work in P2Pool
First you need to find a pool share. This share will stay in PPLNS window for 2160 pool blocks (6 hours). The moment P2Pool finds a Monero block and you have at least 1 pool share in PPLNS window, you'll get a payout! Monero block reward is split between all miner wallets in PPLNS window. Each miner gets a part of block reward proportional to the total difficulty of his/her shares in PPLNS window.
First you need to find a pool share. This share will stay in [PPLNS](https://en.wikipedia.org/wiki/Mining_pool#Pay-per-last-N-shares) window for up to 2160 pool blocks (6 hours, auto adjustable to balance payout sizes and frequency). The moment P2Pool finds a Monero block and you have at least 1 pool share in PPLNS window, you'll get a payout! Monero block reward is split between all miner wallets in PPLNS window. Each miner gets a part of block reward proportional to the total difficulty of his/her shares in PPLNS window.
**NOTE** If P2Pool doesn't have enough hashrate to find Monero blocks faster than every 6 hours on average (~15 MH/s), **not all your pool shares will result in a payout**. Even if pool hashrate is higher, bad luck can sometimes result in a share going through PPLNS window without a payout. But in the long run it will be compensated by other shares receiving multiple payouts - your payouts will average out to what you'd get with regular pool mining.
## Default P2Pool parameters
* Block time: 10 seconds
* PPLNS window: up to 2160 blocks (6 hours), auto adjustable to balance payout sizes and frequency
* Minimum payout = Monero block reward/2160, ~0.0003 XMR
* PPLNS window: up to 2160 blocks (6 hours, auto adjustable to balance payout sizes and frequency)
* Minimum payout = Monero block reward/2160, ~0.00027 XMR
## Monero version support
Monero network upgrade happened on August 13th, 2022 (block 2,688,888). In order to continue mining, you must update both Monero and P2Pool software to the latest available versions as soon as they are released.
- The latest Monero network upgrade happened on August 13th, 2022 (block 2,688,888).
- The latest P2Pool network upgrade happened on March 18th, 2023 at 21:00 UTC.
In order to continue mining on P2Pool, you must update both Monero and P2Pool software to the latest available versions as soon as they are released.
|Monero protocol version|Required Monero software version|Required P2Pool version
|-|-|-|
@@ -89,7 +88,7 @@ Monero network upgrade happened on August 13th, 2022 (block 2,688,888). In order
- In order to mine on P2Pool, a synced Monero node using monerod v0.18.0.0 or newer is required. If you don't currently have one, you can download the official Monero binaries, start `monerod` on your PC and wait until it's fully synced. Advanced Monero node setup instructions are [here](https://sethforprivacy.com/guides/run-a-monero-node-advanced/).
- It is highly recommended that you create a separate restricted user account (in your OS) for mining. While P2Pool has been battle-tested for a long time now, any software may have unknown bugs/vulnerabilities.
- You have to use a primary wallet address for mining. Subaddresses and integrated addresses are not supported, just like with monerod solo mining.
- You have to use a primary wallet address (the one starting with `4`) for mining. Subaddresses and integrated addresses are not supported, just like with monerod solo mining.
- You can add the `--mini` parameter to your P2Pool command to connect to the **p2pool-mini** sidechain. Note that it will also change the default p2p port from 37889 to 37888.
- Check that ports 18080 (Monero p2p port) and 37889/37888 (P2Pool/P2Pool mini p2p port) are open in your firewall to ensure better connectivity. If you're mining from a computer behind NAT (like a router) you could consider forwarding the ports to your local machine.
- You can connect multiple miners to the same P2Pool node. The more the better!
@@ -113,21 +112,21 @@ Monero network upgrade happened on August 13th, 2022 (block 2,688,888). In order
1. Download the latest P2Pool binaries [here](https://github.com/SChernykh/p2pool/releases/latest).
- Alternatively, grab the latest source code for P2Pool and [build it](#build-instructions).
2. Download the latest XMRig (linux-static-x64) binary [here](https://github.com/xmrig/xmrig/releases/latest).
3. Prepare enough huge pages (required for each instance of monerod/P2Pool/XMRig):
3. Prepare enough huge pages (each of monerod/P2Pool/XMRig needs them):
```
sudo sysctl vm.nr_hugepages=3072
```
4. Check that ports 18080 (Monero p2p port) and 37889/37888 (P2Pool/P2Pool mini p2p port) are open in your local firewall to ensure better connectivity.
5. Start `monerod` with the following command/options:
```
./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=node.supportxmr.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
```
**Note:**
The `--zmq-pub` option is required for P2Pool to work properly.
`--out-peers 64 --in-peers 32` is needed to (1) have many connections to other nodes and (2) limit incoming connection count because it can grow uncontrollably and cause problems when it goes above 1000 (open files limit in Linux). If your network connection's **upload** bandwidth is less than **10 Mbit**, use `--out-peers 16 --in-peers 8` instead.
`--add-priority-node=node.supportxmr.com:18080 --add-priority-node=nodes.hashvault.pro:18080` is needed to have guaranteed good working nodes in your connected peers.
`--add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080` is needed to have guaranteed good working nodes in your connected peers.
`--disable-dns-checkpoints` is needed to avoid periodical lags when DNS is updated (it's not needed when mining)
@@ -178,7 +177,7 @@ nocreate
2. Download the latest XMRig binary [here](https://github.com/xmrig/xmrig/releases/latest).
3. Expand the P2Pool binaries into an appropriate location (`%USERPROFILE%/bin` or `C:/bin/` are good options)
4. Expand XMRig binary into an appropriate location (the same folder as P2Pool is fine).
5. Prepare huge pages to work properly (each instance of monerod/P2Pool/XMRig needs them):
5. Prepare huge pages to work properly (each of monerod/P2Pool/XMRig needs them):
- On Windows 10 or above, run XMRig at least once as Administrator (right-click Run As Administrator)
- On earlier versions of Windows, you'll need to run XMRig as Administrator at least once per login.
6. Create "Monero" folder inside extracted P2Pool folder and copy Monero binaries there.
@@ -188,14 +187,14 @@ nocreate
8. Start `monerod` with the following command/options:
```
.\Monero\monerod.exe --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=node.supportxmr.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
.\Monero\monerod.exe --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
```
**Note:**
The `--zmq-pub` option is required for P2Pool to work properly.
`--out-peers 64 --in-peers 32` is needed to (1) have many connections to other nodes and (2) limit incoming connection count because it can grow uncontrollably and cause problems when it goes above 1000 (open files limit in Linux). If your network connection's **upload** bandwidth is less than **10 Mbit**, use `--out-peers 16 --in-peers 8` instead.
`--add-priority-node=node.supportxmr.com:18080 --add-priority-node=nodes.hashvault.pro:18080` is needed to have guaranteed good working nodes in your connected peers.
`--add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080` is needed to have guaranteed good working nodes in your connected peers.
`--disable-dns-checkpoints` is needed to avoid periodical lags when DNS is updated (it's not needed when mining)
@@ -219,7 +218,7 @@ The `--zmq-pub` option is required for P2Pool to work properly.
13. *(Optional but highly recommended)* You can create a Quickstart by creating a batch (.bat) file with the following contents and placing it in your P2Pool directory along with `xmrig.exe`.
```
@ECHO OFF
start cmd /k %~dp0\Monero\monerod.exe --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=node.supportxmr.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
start cmd /k %~dp0\Monero\monerod.exe --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
ECHO Wait until the Monero daemon shows fully synced before continuing. This can take some time. Type 'status' in other window to check progress.
PAUSE
start cmd /k %~dp0\p2pool.exe --wallet YOUR_WALLET_ADDRESS --mini
+9 -2
View File
@@ -68,10 +68,17 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
set(GENERAL_FLAGS "-pthread")
if (WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
else()
set(GENERAL_FLAGS "-pthread")
endif()
set(WARNING_FLAGS "-Wall -Wextra -Wno-undefined-internal -Wunreachable-code-aggressive -Wmissing-prototypes -Wmissing-variable-declarations -Werror")
if (NOT DEV_WITH_MSAN)
if (DEV_WITH_MSAN)
set(OPTIMIZATION_FLAGS "-O2 -g")
else()
set(OPTIMIZATION_FLAGS "-Ofast -funroll-loops -fmerge-all-constants")
endif()
-11
View File
@@ -1,11 +0,0 @@
../src/
../external/src/
../external/src/cryptonote/
../external/src/libuv/include/
../external/src/cppzmq/
../external/src/libzmq/include/
../external/src/curl/include
../external/src/RandomX/src/
../external/src/rapidjson/include
../external/src/robin-hood-hashing/src/include
../external/src/miniupnp/miniupnpc/include
+15
View File
@@ -0,0 +1,15 @@
import sys
import json
f = open(sys.argv[1])
data = json.load(f)
f.close()
v = []
for el in data:
if not ("/external/" in el['file']):
v.append(el)
f = open(sys.argv[1], 'w')
json.dump(v, f, indent=2)
f.close()
+1 -1
View File
@@ -1,5 +1,5 @@
@echo off
"..\cppcheck-main\bin\cppcheck.exe" --project=..\build\p2pool.vcxproj --project-configuration="Release|x64" -DSIZE_MAX=UINT64_MAX -DRAPIDJSON_ENDIAN=RAPIDJSON_LITTLEENDIAN --platform=win64 --std=c++14 --enable=all --inconclusive --inline-suppr --template="{file}:{line}:{id}{inconclusive: INCONCLUSIVE} {message}" --includes-file=includes.txt --suppressions-list=suppressions.txt --output-file=errors_full.txt
"..\cppcheck-main\bin\cppcheck.exe" --project=..\build\p2pool.vcxproj --project-configuration="Release|x64" -DSIZE_MAX=UINT64_MAX -DRAPIDJSON_ENDIAN=RAPIDJSON_LITTLEENDIAN --platform=win64 --std=c++14 --enable=all --inconclusive --inline-suppr --template="{file}:{line}:{id}{inconclusive: INCONCLUSIVE} {message}" --suppressions-list=suppressions.txt --output-file=errors_full.txt --max-ctu-depth=3 --check-level=exhaustive
findstr /V /C:"external\src" errors_full.txt > errors_filtered.txt
for /f %%i in ("errors_filtered.txt") do set size=%%~zi
if %size% gtr 0 (
+1 -1
View File
@@ -1,5 +1,5 @@
#!/bin/bash
../cppcheck-main/cppcheck ../src -DSIZE_MAX=UINT64_MAX -DRAPIDJSON_ENDIAN=RAPIDJSON_LITTLEENDIAN --platform=unix64 --std=c++14 --enable=all --inconclusive --inline-suppr --template="{file}:{line}:{id}{inconclusive: INCONCLUSIVE} {message}" --includes-file=includes.txt --suppressions-list=suppressions.txt --output-file=errors_full.txt
../cppcheck-main/cppcheck --project=../build/compile_commands.json -DSIZE_MAX=UINT64_MAX -DRAPIDJSON_ENDIAN=RAPIDJSON_LITTLEENDIAN -D__SSE2__=1 --platform=unix64 --std=c++14 --enable=all --inconclusive --inline-suppr --template="{file}:{line}:{id}{inconclusive: INCONCLUSIVE} {message}" --suppressions-list=suppressions.txt --output-file=errors_full.txt --max-ctu-depth=3 --check-level=exhaustive
grep -v 'external' errors_full.txt > errors_filtered.txt
if [ -s errors_filtered.txt ]; then
cat errors_filtered.txt
+15
View File
@@ -34,4 +34,19 @@
### Example command line
```
p2pool.exe --host 127.0.0.1 --rpc-port 18081 --zmq-port 18083 --wallet YOUR_WALLET_ADDRESS --stratum 0.0.0.0:3333 --p2p 0.0.0.0:37889
```
### Multiple backup hosts
You can have multiple hosts in command line. If P2Pool detects that the host it's currently using is down or stuck, it will cycle through hosts until it finds a working one. It will not switch back as long as the current host it found is working.
Each new host uses RPC and zmq-pub port numbers from the previous host (or default 18081/18083 if none were specified). Note that `--rpc-login` is not copied from the previous host, you must specify it for each host that has username/password.
In this example, you have local Monero host running on ports 18081/18083 (RPC/zmq-pub), and several backup hosts running on ports 18089/18084.
```
p2pool.exe --host 127.0.0.1 --host xmr1.rs.me --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --host xmr3.rs.me --wallet YOUR_WALLET_ADDRESS
```
+20
View File
@@ -0,0 +1,20 @@
### P2Pool console commands
Command|Description
-|-
help|display list of commands
status|display p2pool status
loglevel **N**|set log level (**N** can be between 0 and 6)
addpeers **L**|**L** is a comma-separated list of IP:port of other p2pool nodes to connect to
droppeers|disconnect all currently connected peers
peers|show all currently connected peers (p2p)
workers|show all currently connected workers (stratum)
bans|show all banned IPs
hosts|show Monero hosts which were configured in the command line
next_host|switch to the next Monero host configured in the command line
outpeers **N**|set maximum number of outgoing connections (values above 50 are not recommended)
inpeers **N**|set maximum number of incoming connections (values above 50 are not recommended)
start_mining **T**|start mining (**T** is the number of threads to use, must be between 1 and 64)
stop_mining|stop mining
exit|terminate p2pool
version|show p2pool version
+1 -1
View File
@@ -241,7 +241,7 @@ It's highly recommended to create a new wallet for mining because wallet address
<ul>
<li>Download the latest Monero <a href="https://www.getmonero.org/downloads/" target="_blank">release</a>
<li>[Optional] Open port <span>18080</span> (Monero p2p port) in your firewall to ensure better connectivity
<li>Run <span>./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=node.supportxmr.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist</span>
<li>Run <span>./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist</span>
<li>If your network connection's upload bandwidth is less than 10 Mbit, use <span>--out-peers 16 --in-peers 8</span> instead.
<li>Wait until it's fully synchronized. If you didn't run Monero node before, it can take up to several days to synchronize (5-6 hours on a modern PC with fast SSD and fast Internet connection). You can add <span>--prune-blockchain</span> argument to the command line to run a pruned node (3-4 times less disk usage)
</ul></details>
+1 -1
View File
@@ -241,7 +241,7 @@ It's highly recommended to create a new wallet for mining because wallet address
<ul>
<li>Download the latest Monero <a href="https://www.getmonero.org/downloads/" target="_blank">release</a>
<li>[Optional] Open port <span>18080</span> (Monero p2p port) in your firewall to ensure better connectivity
<li>Run <span>./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=node.supportxmr.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist</span>
<li>Run <span>./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist</span>
<li>If your network connection's upload bandwidth is less than 10 Mbit, use <span>--out-peers 16 --in-peers 8</span> instead.
<li>Wait until it's fully synchronized. If you didn't run Monero node before, it can take up to several days to synchronize (5-6 hours on a modern PC with fast SSD and fast Internet connection). You can add <span>--prune-blockchain</span> argument to the command line to run a pruned node (3-4 times less disk usage)
</ul></details>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -20,7 +20,7 @@
#include "pool_block.h"
#include "p2p_server.h"
static constexpr char log_category_prefix[] = "BlockCache ";
LOG_CATEGORY(BlockCache)
static constexpr uint32_t BLOCK_SIZE = 96 * 1024;
static constexpr uint32_t NUM_BLOCKS = 4608;
+1 -1
View File
@@ -32,7 +32,7 @@
#include <ctime>
#include <numeric>
static constexpr char log_category_prefix[] = "BlockTemplate ";
LOG_CATEGORY(BlockTemplate)
namespace p2pool {
+18 -7
View File
@@ -67,10 +67,18 @@
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#endif
#include <Windows.h>
#elif defined(__linux__) || defined(__unix__) || defined(_POSIX_VERSION) || defined(__MACH__)
@@ -152,8 +160,8 @@ struct alignas(uint64_t) hash
FORCEINLINE bool operator<(const hash& other) const
{
const uint64_t* a = reinterpret_cast<const uint64_t*>(h);
const uint64_t* b = reinterpret_cast<const uint64_t*>(other.h);
const uint64_t* a = u64();
const uint64_t* b = other.u64();
if (a[3] < b[3]) return true;
if (a[3] > b[3]) return false;
@@ -169,18 +177,21 @@ struct alignas(uint64_t) hash
FORCEINLINE bool operator==(const hash& other) const
{
const uint64_t* a = reinterpret_cast<const uint64_t*>(h);
const uint64_t* b = reinterpret_cast<const uint64_t*>(other.h);
const uint64_t* a = u64();
const uint64_t* b = other.u64();
return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
}
FORCEINLINE bool operator!=(const hash& other) const { return !operator==(other); }
FORCEINLINE bool empty() const {
const uint64_t* a = reinterpret_cast<const uint64_t*>(h);
const uint64_t* a = u64();
return (a[0] == 0) && (a[1] == 0) && (a[2] == 0) && (a[3] == 0);
}
FORCEINLINE uint64_t* u64() { return reinterpret_cast<uint64_t*>(h); }
FORCEINLINE const uint64_t* u64() const { return reinterpret_cast<const uint64_t*>(h); }
friend std::ostream& operator<<(std::ostream& s, const hash& d);
friend std::istream& operator>>(std::istream& s, hash& d);
};
@@ -204,7 +215,7 @@ struct
{
#ifdef _MSC_VER
_addcarry_u64(_addcarry_u64(0, lo, b.lo, &lo), hi, b.hi, &hi);
#elif __GNUC__
#elif defined(__GNUC__) && !defined(DEV_CLANG_TIDY)
*reinterpret_cast<unsigned __int128*>(this) += *reinterpret_cast<const unsigned __int128*>(&b);
#else
const uint64_t t = lo;
@@ -221,7 +232,7 @@ struct
{
#ifdef _MSC_VER
_subborrow_u64(_subborrow_u64(0, lo, b.lo, &lo), hi, b.hi, &hi);
#elif __GNUC__
#elif defined(__GNUC__) && !defined(DEV_CLANG_TIDY)
*reinterpret_cast<unsigned __int128*>(this) -= *reinterpret_cast<const unsigned __int128*>(&b);
#else
const uint64_t t = b.lo;
+74 -40
View File
@@ -28,7 +28,7 @@
#include "p2pool_api.h"
#include "params.h"
static constexpr char log_category_prefix[] = "ConsoleCommands ";
LOG_CATEGORY(ConsoleCommands)
static constexpr int DEFAULT_BACKLOG = 1;
@@ -47,7 +47,41 @@ ConsoleCommands::ConsoleCommands(p2pool* pool)
LOGINFO(3, "uv_guess_handle returned " << static_cast<int>(stdin_type));
if (stdin_type != UV_TTY && stdin_type != UV_NAMED_PIPE) {
LOGERR(1, "tty or named pipe is not available");
throw std::exception();
}
int err;
if (stdin_type == UV_TTY) {
LOGINFO(3, "processing stdin as UV_TTY");
err = uv_tty_init(&m_loop, &m_tty, 0, 1);
if (err) {
LOGERR(1, "uv_tty_init failed, error " << uv_err_name(err));
throw std::exception();
}
m_stdin_handle = reinterpret_cast<uv_stream_t*>(&m_tty);
}
else if (stdin_type == UV_NAMED_PIPE) {
LOGINFO(3, "processing stdin as UV_NAMED_PIPE");
err = uv_pipe_init(&m_loop, &m_stdin_pipe, 0);
if (err) {
LOGERR(1, "uv_pipe_init failed, error " << uv_err_name(err));
throw std::exception();
}
m_stdin_handle = reinterpret_cast<uv_stream_t*>(&m_stdin_pipe);
err = uv_pipe_open(&m_stdin_pipe, 0);
if (err) {
LOGERR(1, "uv_pipe_open failed, error " << uv_err_name(err));
throw std::exception();
}
}
if (m_stdin_handle) {
m_stdin_handle->data = this;
err = uv_read_start(m_stdin_handle, allocCallback, stdinReadCallback);
if (err) {
LOGERR(1, "uv_read_start failed, error " << uv_err_name(err));
throw std::exception();
}
}
std::random_device rd;
@@ -67,50 +101,29 @@ ConsoleCommands::ConsoleCommands(p2pool* pool)
m_pool->api()->set(p2pool_api::Category::LOCAL, "console",
[stdin_type, this](log::Stream& s)
{
s << "{\"mode\":" << ((stdin_type == UV_TTY) ? "\"tty\"" : "\"pipe\"")
<< ",\"tcp_port\":" << m_listenPort
<< "}";
s << "{\"mode\":\"";
if (stdin_type == UV_TTY) {
s << "tty";
}
else if (stdin_type == UV_NAMED_PIPE) {
s << "pipe";
}
else {
s << static_cast<int>(stdin_type);
}
s << "\",\"tcp_port\":" << m_listenPort << '}';
});
}
int err;
if (stdin_type == UV_TTY) {
LOGINFO(3, "processing stdin as UV_TTY");
err = uv_tty_init(&m_loop, &m_tty, 0, 1);
if (err) {
LOGERR(1, "uv_tty_init failed, error " << uv_err_name(err));
throw std::exception();
}
m_stdin_handle = reinterpret_cast<uv_stream_t*>(&m_tty);
}
else {
LOGINFO(3, "processing stdin as UV_NAMED_PIPE");
err = uv_pipe_init(&m_loop, &m_stdin_pipe, 0);
if (err) {
LOGERR(1, "uv_pipe_init failed, error " << uv_err_name(err));
throw std::exception();
}
m_stdin_handle = reinterpret_cast<uv_stream_t*>(&m_stdin_pipe);
err = uv_pipe_open(&m_stdin_pipe, 0);
if (err) {
LOGERR(1, "uv_pipe_open failed, error " << uv_err_name(err));
throw std::exception();
}
}
m_stdin_handle->data = this;
err = uv_read_start(m_stdin_handle, allocCallback, stdinReadCallback);
if (err) {
LOGERR(1, "uv_read_start failed, error " << uv_err_name(err));
throw std::exception();
}
err = uv_thread_create(&m_loopThread, loop, this);
if (err) {
LOGERR(1, "failed to start event loop thread, error " << uv_err_name(err));
throw std::exception();
}
m_loopThreadCreated = true;
}
ConsoleCommands::~ConsoleCommands()
@@ -120,7 +133,14 @@ ConsoleCommands::~ConsoleCommands()
void ConsoleCommands::on_shutdown()
{
uv_close(reinterpret_cast<uv_handle_t*>(m_stdin_handle), nullptr);
if (m_stdin_handle) {
uv_close(reinterpret_cast<uv_handle_t*>(m_stdin_handle), nullptr);
}
}
const char* ConsoleCommands::get_log_category() const
{
return log_category_prefix;
}
typedef struct strconst {
@@ -140,7 +160,7 @@ typedef struct cmd {
cmdfunc *func;
} cmd;
static cmdfunc do_help, do_status, do_loglevel, do_addpeers, do_droppeers, do_showpeers, do_showworkers, do_showbans, do_outpeers, do_inpeers, do_exit, do_version;
static cmdfunc do_help, do_status, do_loglevel, do_addpeers, do_droppeers, do_showpeers, do_showworkers, do_showbans, do_showhosts, do_nexthost, do_outpeers, do_inpeers, do_exit, do_version;
#ifdef WITH_RANDOMX
static cmdfunc do_start_mining, do_stop_mining;
@@ -155,6 +175,8 @@ static cmd cmds[] = {
{ STRCONST("peers"), "", "show all peers", do_showpeers },
{ STRCONST("workers"), "", "show all connected workers", do_showworkers },
{ STRCONST("bans"), "", "show all banned IPs", do_showbans },
{ STRCONST("hosts"), "", "show Monero hosts", do_showhosts },
{ STRCONST("next_host"), "", "switch to the next Monero host", do_nexthost },
{ STRCONST("outpeers"), "<N>", "set maximum number of outgoing connections", do_outpeers },
{ STRCONST("inpeers"), "<N>", "set maximum number of incoming connections", do_inpeers },
#ifdef WITH_RANDOMX
@@ -240,6 +262,18 @@ static void do_showbans(p2pool* m_pool, const char* /* args */)
}
}
// cppcheck-suppress constParameterCallback
static void do_showhosts(p2pool* m_pool, const char* /* args */)
{
m_pool->print_hosts();
}
// cppcheck-suppress constParameterCallback
static void do_nexthost(p2pool* m_pool, const char* /* args */)
{
m_pool->reconnect_to_host();
}
// cppcheck-suppress constParameterCallback
static void do_outpeers(p2pool* m_pool, const char* args)
{
+1 -1
View File
@@ -50,7 +50,7 @@ public:
void on_shutdown() override;
private:
const char* get_category() const override { return "ConsoleCommands "; }
const char* get_log_category() const override;
p2pool* m_pool;
+28 -7
View File
@@ -20,7 +20,7 @@
#include "json_rpc_request.h"
#include <curl/curl.h>
static constexpr char log_category_prefix[] = "JSONRPCRequest ";
LOG_CATEGORY(JSONRPCRequest)
namespace p2pool {
namespace JSONRPCRequest {
@@ -78,6 +78,9 @@ struct CurlContext
std::string m_error;
curl_slist* m_headers;
uint64_t m_startTime;
uint64_t m_connectedTime;
};
CurlContext::CurlContext(const std::string& address, int port, const std::string& req, const std::string& auth, const std::string& proxy, CallbackBase* cb, CallbackBase* close_cb, uv_loop_t* loop)
@@ -90,6 +93,8 @@ CurlContext::CurlContext(const std::string& address, int port, const std::string
, m_handle(nullptr)
, m_req(req)
, m_headers(nullptr)
, m_startTime(0)
, m_connectedTime(0)
{
m_pollHandles.reserve(2);
@@ -214,12 +219,19 @@ CurlContext::CurlContext(const std::string& address, int port, const std::string
uv_close(reinterpret_cast<uv_handle_t*>(&m_timer), nullptr);
throw std::runtime_error("curl_multi_add_handle failed");
}
m_startTime = microseconds_since_epoch();
}
CurlContext::~CurlContext()
{
double tcp_ping = 0.0;
if (m_error.empty() && !m_response.empty()) {
(*m_callback)(m_response.data(), m_response.size());
if (m_connectedTime) {
tcp_ping = static_cast<double>(m_connectedTime - m_startTime) / 1000.0;
}
(*m_callback)(m_response.data(), m_response.size(), tcp_ping);
}
delete m_callback;
@@ -232,7 +244,7 @@ CurlContext::~CurlContext()
}
}
(*m_closeCallback)(m_error.c_str(), m_error.length());
(*m_closeCallback)(m_error.c_str(), m_error.length(), tcp_ping);
delete m_closeCallback;
curl_slist_free_all(m_headers);
@@ -361,6 +373,10 @@ void CurlContext::on_timeout(uv_handle_t* req)
size_t CurlContext::on_write(const void* buffer, size_t size, size_t count)
{
if (!m_connectedTime) {
m_connectedTime = microseconds_since_epoch();
}
const size_t realsize = size * count;
const char* p = reinterpret_cast<const char*>(buffer);
m_response.insert(m_response.end(), p, p + realsize);
@@ -369,6 +385,8 @@ size_t CurlContext::on_write(const void* buffer, size_t size, size_t count)
void CurlContext::curl_perform(uv_poll_t* req, int status, int events)
{
CurlContext* ctx = reinterpret_cast<CurlContext*>(req->data);
int flags = 0;
if (status < 0) {
flags |= CURL_CSELECT_ERR;
@@ -376,11 +394,14 @@ void CurlContext::curl_perform(uv_poll_t* req, int status, int events)
}
else {
if (events & UV_READABLE) flags |= CURL_CSELECT_IN;
if (events & UV_WRITABLE) flags |= CURL_CSELECT_OUT;
if (events & UV_WRITABLE) {
flags |= CURL_CSELECT_OUT;
if (!ctx->m_connectedTime) {
ctx->m_connectedTime = microseconds_since_epoch();
}
}
}
CurlContext* ctx = reinterpret_cast<CurlContext*>(req->data);
int running_handles = 0;
auto it = std::find_if(ctx->m_pollHandles.begin(), ctx->m_pollHandles.end(), [req](const auto& value) { return value.second == req; });
if (it != ctx->m_pollHandles.end()) {
@@ -471,7 +492,7 @@ void Call(const std::string& address, int port, const std::string& req, const st
}
catch (const std::exception& e) {
const char* msg = e.what();
(*close_cb)(msg, strlen(msg));
(*close_cb)(msg, strlen(msg), 0.0);
}
});
+3 -3
View File
@@ -20,15 +20,15 @@
namespace p2pool {
namespace JSONRPCRequest {
typedef Callback<void, const char*, size_t>::Base CallbackBase;
typedef Callback<void, const char*, size_t, double>::Base CallbackBase;
void Call(const std::string& address, int port, const std::string& req, const std::string& auth, const std::string& proxy, CallbackBase* cb, CallbackBase* close_cb, uv_loop_t* loop);
template<typename T, typename U>
FORCEINLINE void call(const std::string& address, int port, const std::string& req, const std::string& auth, const std::string& proxy, T&& cb, U&& close_cb, uv_loop_t* loop = nullptr)
{
typedef Callback<void, const char*, size_t>::Derived<T> CallbackT;
typedef Callback<void, const char*, size_t>::Derived<U> CallbackU;
typedef Callback<void, const char*, size_t, double>::Derived<T> CallbackT;
typedef Callback<void, const char*, size_t, double>::Derived<U> CallbackU;
Call(address, port, req, auth, proxy, new CallbackT(std::move(cb)), new CallbackU(std::move(close_cb)), loop);
}
+2 -1
View File
@@ -27,7 +27,8 @@
#pragma warning(disable : 4996)
#endif
static constexpr char log_category_prefix[] = "Log ";
LOG_CATEGORY(Log)
static constexpr char log_file_name[] = "p2pool.log";
namespace p2pool {
+36 -19
View File
@@ -65,7 +65,7 @@ struct Stream
return *this;
}
template<typename T, int base = 10>
template<typename T, unsigned int base = 10>
NOINLINE void writeInt(T data)
{
static_assert(1 < base && base <= 64, "Invalid base");
@@ -78,11 +78,13 @@ struct Stream
size_t k = sizeof(buf);
int w = m_numberWidth;
std::make_unsigned_t<T> udata = static_cast<std::make_unsigned_t<T>>(data);
do {
buf[--k] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/"[data % base];
data /= base;
buf[--k] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/"[udata % base];
udata /= base;
--w;
} while ((data > 0) || (w > 0));
} while (udata || (w > 0));
if (negative) {
buf[--k] = '-';
@@ -144,7 +146,13 @@ COLOR_ENTRY(LightCyan, "\x1b[0;96m")
template<size_t N> struct Stream::Entry<char[N]>
{
static FORCEINLINE void put(const char (&data)[N], Stream* wrapper) { wrapper->writeBuf(data, N - 1); }
template<typename T>
// cppcheck-suppress constParameterReference
static FORCEINLINE void put(T (&data)[N], Stream* wrapper)
{
static_assert(std::is_same<T, const char>::value, "Non-const char buffer must be cast to \"const char*\"");
wrapper->writeBuf(data, N - 1);
}
};
template<> struct Stream::Entry<const char*>
@@ -154,6 +162,7 @@ template<> struct Stream::Entry<const char*>
template<> struct Stream::Entry<char*>
{
// cppcheck-suppress constParameterPointer
static FORCEINLINE void put(char* data, Stream* wrapper) { wrapper->writeBuf(data, strlen(data)); }
};
@@ -279,7 +288,10 @@ template<> struct log::Stream::Entry<const_buf>
struct hex_buf
{
FORCEINLINE hex_buf(const uint8_t* data, size_t size) : m_data(data), m_size(size) {}
FORCEINLINE hex_buf(const void* data, size_t size) : m_data(reinterpret_cast<const uint8_t*>(data)), m_size(size) {}
template<typename T>
explicit FORCEINLINE hex_buf(const T* data) : m_data(reinterpret_cast<const uint8_t*>(data)), m_size(sizeof(T)) {}
const uint8_t* m_data;
size_t m_size;
@@ -484,28 +496,33 @@ struct DummyStream
}
};
#ifdef __COVERITY__
// Coverity doesn't like this macro - CID 393138: Big parameter passed by value (PASS_BY_VALUE)
#define SIDE_EFFECT_CHECK(level, ...)
#else
#define SIDE_EFFECT_CHECK(level, ...) \
do { \
if (0) { \
MSVC_PRAGMA(warning(suppress:26444)) \
[=]() { \
log::DummyStream x; \
x << (level) << __VA_ARGS__; \
}; \
} \
} while (0)
if (0) { \
MSVC_PRAGMA(warning(suppress:26444)) \
[=]() { \
log::DummyStream x; \
x << (level) << __VA_ARGS__; \
}; \
}
#endif
#define LOG_CATEGORY(category) static constexpr char log_category_prefix[] = #category " ";
#ifdef P2POOL_LOG_DISABLE
#define LOGINFO(level, ...) SIDE_EFFECT_CHECK(level, __VA_ARGS__)
#define LOGWARN(level, ...) SIDE_EFFECT_CHECK(level, __VA_ARGS__)
#define LOGERR(level, ...) SIDE_EFFECT_CHECK(level, __VA_ARGS__)
#define LOGINFO(level, ...) SIDE_EFFECT_CHECK(level, log_category_prefix << __VA_ARGS__)
#define LOGWARN(level, ...) SIDE_EFFECT_CHECK(level, log_category_prefix << __VA_ARGS__)
#define LOGERR(level, ...) SIDE_EFFECT_CHECK(level, log_category_prefix << __VA_ARGS__)
#else
#define LOG(level, severity, ...) \
do { \
SIDE_EFFECT_CHECK(level, __VA_ARGS__); \
SIDE_EFFECT_CHECK(level, log_category_prefix << __VA_ARGS__); \
if ((level) <= log::GLOBAL_LOG_LEVEL) { \
log::Writer CONCAT(log_wrapper_, __LINE__)(severity); \
CONCAT(log_wrapper_, __LINE__) << log::Gray() << log_category_prefix; \
+59 -3
View File
@@ -22,6 +22,10 @@
#include "p2p_server.h"
#include <curl/curl.h>
#ifdef WITH_RANDOMX
#include "randomx.h"
#endif
void p2pool_usage()
{
printf("P2Pool %s\n"
@@ -81,8 +85,54 @@ void p2pool_version()
printf("P2Pool %s\n", p2pool::VERSION);
}
void memory_tracking_start();
void memory_tracking_stop();
int p2pool_test()
{
#ifdef WITH_RANDOMX
const char myKey[] = "test key 000";
const char myInput[] = "This is a test";
char hash[RANDOMX_HASH_SIZE];
const randomx_flags flags = randomx_get_flags() | RANDOMX_FLAG_FULL_MEM;
randomx_cache* myCache = randomx_alloc_cache(flags);
if (!myCache) {
printf("Cache allocation failed\n");
return 1;
}
randomx_init_cache(myCache, myKey, sizeof(myKey) - 1);
randomx_dataset* myDataset = randomx_alloc_dataset(flags);
if (!myDataset) {
printf("Dataset allocation failed\n");
return 1;
}
randomx_init_dataset(myDataset, myCache, 0, randomx_dataset_item_count());
randomx_release_cache(myCache);
randomx_vm* myMachine = randomx_create_vm(flags, nullptr, myDataset);
if (!myMachine) {
printf("Failed to create a virtual machine");
return 1;
}
randomx_calculate_hash(myMachine, &myInput, sizeof(myInput) - 1, hash);
char buf[RANDOMX_HASH_SIZE * 2 + 1] = {};
p2pool::log::Stream s(buf);
s << p2pool::log::hex_buf(hash, RANDOMX_HASH_SIZE);
if (memcmp(buf, "639183aae1bf4c9a35884cb46b09cad9175f04efd7684e7262a0ac1c2f0b4e3f", RANDOMX_HASH_SIZE * 2) != 0) {
printf("Invalid hash calculated\n");
return 1;
}
randomx_destroy_vm(myMachine);
randomx_release_dataset(myDataset);
#endif
printf("Self-test passed\n");
return 0;
}
int main(int argc, char* argv[])
{
@@ -101,6 +151,10 @@ int main(int argc, char* argv[])
p2pool_version();
return 0;
}
if (!strcmp(argv[i], "--test")) {
return p2pool_test();
}
}
memory_tracking_start();
@@ -124,7 +178,9 @@ int main(int argc, char* argv[])
p2pool::destroy_crypto_cache();
memory_tracking_stop();
if (!memory_tracking_stop()) {
result = 1;
}
return result;
}
+17 -5
View File
@@ -18,11 +18,12 @@
#include "common.h"
// Simple memory leak detector for Windows users, works best in RelWithDebInfo configuration.
#if defined(_WIN32) && 0
#if defined(_WIN32) && defined(DEV_TRACK_MEMORY)
#include "uv_util.h"
#include <atomic>
#include <type_traits>
#include <iostream>
#include <DbgHelp.h>
@@ -87,7 +88,7 @@ uint32_t num_allocations = 0;
uint64_t total_allocated = 0;
uint32_t cur_allocation_index = 1;
void show_top_10()
void show_top_10_allocations()
{
TrackedAllocation* buf = reinterpret_cast<TrackedAllocation*>(VirtualAlloc(nullptr, sizeof(TrackedAllocation) * N, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
if (!buf) {
@@ -122,7 +123,8 @@ void show_top_10()
std::sort(buf, end, [](const auto& a, const auto& b) { return a.allocated_size > b.allocated_size; });
printf("%I64u total bytes allocated\n", total_allocated);
printf("%I64u total bytes allocated\n\n", total_allocated);
printf("Top 10 allocations:\n\n");
for (TrackedAllocation* p = buf; (p < buf + 10) && (p < end); ++p) {
printf("%I64u bytes allocated at:\n", p->allocated_size);
@@ -130,6 +132,8 @@ void show_top_10()
}
}
printf("\n");
VirtualFree(buf, 0, MEM_RELEASE);
}
@@ -263,6 +267,9 @@ void* calloc_hook(size_t count, size_t size) noexcept
void memory_tracking_start()
{
// Trigger std::ostream initialization to avoid reporting it as leaks
std::cout << "Memory leak detection = " << 1 << std::endl;
SymInitialize(GetCurrentProcess(), NULL, TRUE);
using namespace p2pool;
@@ -272,7 +279,7 @@ void memory_tracking_start()
track_memory = true;
}
void memory_tracking_stop()
bool memory_tracking_stop()
{
using namespace p2pool;
@@ -296,8 +303,13 @@ void memory_tracking_stop()
if (total_leaks > 0) {
printf("%I64u bytes leaked\n\n", total_leaks);
}
else {
printf("No memory leaks detected\n\n");
}
SymCleanup(h);
return (total_leaks == 0);
}
NOINLINE void* operator new(size_t n) { return p2pool::allocate(n); }
@@ -313,7 +325,7 @@ NOINLINE void operator delete[](void* p, size_t) noexcept { p2pool::free_hook(p)
// cppcheck-suppress functionStatic
void memory_tracking_start() {}
// cppcheck-suppress functionStatic
void memory_tracking_stop() {}
bool memory_tracking_stop() { return true; }
namespace p2pool {
+1 -1
View File
@@ -19,7 +19,7 @@
#include "mempool.h"
#include "util.h"
static constexpr char log_category_prefix[] = "Mempool ";
LOG_CATEGORY(Mempool)
namespace p2pool {
+12 -3
View File
@@ -28,7 +28,7 @@
#include "p2p_server.h"
#include <thread>
static constexpr char log_category_prefix[] = "Miner ";
LOG_CATEGORY(Miner)
using namespace std::chrono;
@@ -85,11 +85,11 @@ void Miner::print_status()
const uint64_t hr = (dt > 0.0) ? static_cast<uint64_t>(hash_count / dt) : 0;
char shares_failed_buf[64] = {};
log::Stream s(shares_failed_buf);
const uint32_t shares_found = m_sharesFound;
const uint32_t shares_failed = m_sharesFailed;
if (shares_failed) {
log::Stream s(shares_failed_buf);
s << log::Yellow() << "\nShares failed = " << shares_failed << log::NoColor();
}
@@ -224,7 +224,16 @@ void Miner::run(WorkerData* data)
job[index].set_nonce(static_cast<uint32_t>(full_nonce), static_cast<uint32_t>(full_nonce >> 32));
hash h;
randomx_calculate_hash_next(vm, job[index].m_blob, job[index].m_blobSize, &h);
try {
randomx_calculate_hash_next(vm, job[index].m_blob, job[index].m_blobSize, &h);
}
catch (const std::exception& e) {
LOGERR(0, "Failed to calculate RandomX hash: exception \"" << e.what() << "\". Is your CPU/RAM unstable?" <<
"\nFailed RandomX hash input: " << log::hex_buf(j.m_blob, j.m_blobSize));
// Make the result hash all FF's to fail difficulty checks
memset(h.h, -1, HASH_SIZE);
}
if (j.m_diff.check_pow(h)) {
LOGINFO(0, log::Green() << "worker thread " << data->m_index << '/' << data->m_count << " found a mainchain block at height " << j.m_height << ", submitting it");
+242 -86
View File
@@ -31,13 +31,15 @@
#include <fstream>
#include <numeric>
static constexpr char log_category_prefix[] = "P2PServer ";
LOG_CATEGORY(P2PServer)
static constexpr char saved_peer_list_file_name[] = "p2pool_peers.txt";
static const char* seed_nodes[] = { "seeds.p2pool.io", ""};
static const char* seed_nodes_mini[] = { "seeds-mini.p2pool.io", "" };
static constexpr int DEFAULT_BACKLOG = 16;
static constexpr uint64_t DEFAULT_BAN_TIME = 600;
static constexpr uint64_t PEER_REQUEST_DELAY = 60;
namespace p2pool {
@@ -373,7 +375,7 @@ void P2PServer::update_peer_list()
void P2PServer::send_peer_list_request(P2PClient* client, uint64_t cur_time)
{
// Send peer list requests at random intervals (60-120 seconds)
client->m_nextOutgoingPeerListRequest = cur_time + (60 + (get_random64() % 61));
client->m_nextOutgoingPeerListRequest = cur_time + (PEER_REQUEST_DELAY + (get_random64() % (PEER_REQUEST_DELAY + 1)));
const bool result = send(client,
[client](uint8_t* buf, size_t buf_size)
@@ -615,10 +617,10 @@ void P2PServer::load_peer_list()
void P2PServer::load_monerod_peer_list()
{
const Params& params = m_pool->params();
const Params::Host& host = m_pool->current_host();
JSONRPCRequest::call(params.m_host, params.m_rpcPort, "/get_peer_list", params.m_rpcLogin, m_socks5Proxy,
[this](const char* data, size_t size)
JSONRPCRequest::call(host.m_address, host.m_rpcPort, "/get_peer_list", host.m_rpcLogin, m_socks5Proxy,
[this](const char* data, size_t size, double)
{
#define ERR_STR "/get_peer_list RPC request returned invalid JSON "
@@ -685,7 +687,7 @@ void P2PServer::load_monerod_peer_list()
LOGINFO(4, "monerod peer list loaded (" << m_peerListMonero.size() << " peers)");
},
[](const char* data, size_t size)
[](const char* data, size_t size, double)
{
if (size > 0) {
LOGWARN(4, "/get_peer_list RPC request failed: error " << log::const_buf(data, size));
@@ -882,12 +884,28 @@ void P2PServer::on_broadcast()
{
uint8_t* p = buf;
bool send_pruned = true;
bool send_compact = (client->m_protocolVersion >= PROTOCOL_VERSION_1_1) && !data->compact_blob.empty() && (data->compact_blob.size() < data->pruned_blob.size());
const hash* a = client->m_broadcastedHashes;
const hash* b = client->m_broadcastedHashes + array_size(&P2PClient::m_broadcastedHashes);
// If this peer already broadcasted this block to us, we don't need to broadcast it back, we just need to notify the peer
if ((client->m_protocolVersion >= PROTOCOL_VERSION_1_2) && (std::find(a, b, data->id) != b)) {
LOGINFO(6, "sending BLOCK_NOTIFY to " << log::Gray() << static_cast<char*>(client->m_addrString));
if (buf_size < 1 + HASH_SIZE) {
return 0;
}
*(p++) = static_cast<uint8_t>(MessageId::BLOCK_NOTIFY);
memcpy(p, data->id.h, HASH_SIZE);
p += HASH_SIZE;
return p - buf;
}
bool send_pruned = true;
bool send_compact = (client->m_protocolVersion >= PROTOCOL_VERSION_1_1) && !data->compact_blob.empty() && (data->compact_blob.size() < data->pruned_blob.size());
for (const hash& id : data->ancestor_hashes) {
if (std::find(a, b, id) == b) {
send_pruned = false;
@@ -897,7 +915,7 @@ void P2PServer::on_broadcast()
}
if (send_pruned) {
LOGINFO(6, "sending BLOCK_BROADCAST (" << (send_compact ? "compact" : "pruned") << ") to " << log::Gray() << static_cast<char*>(client->m_addrString));
LOGINFO(6, "sending BLOCK_BROADCAST " << (send_compact ? "(compact)" : "(pruned) ") << " to " << log::Gray() << static_cast<char*>(client->m_addrString));
const std::vector<uint8_t>& blob = send_compact ? data->compact_blob : data->pruned_blob;
const uint32_t len = static_cast<uint32_t>(blob.size());
@@ -916,7 +934,7 @@ void P2PServer::on_broadcast()
}
}
else {
LOGINFO(5, "sending BLOCK_BROADCAST (full) to " << log::Gray() << static_cast<char*>(client->m_addrString));
LOGINFO(5, "sending BLOCK_BROADCAST (full) to " << log::Gray() << static_cast<char*>(client->m_addrString));
const uint32_t len = static_cast<uint32_t>(data->blob.size());
if (buf_size < 1 + sizeof(uint32_t) + len) {
@@ -985,8 +1003,8 @@ void P2PServer::show_peers() const
for (P2PClient* client = static_cast<P2PClient*>(m_connectedClientsList->m_next); client != m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
if (client->m_listenPort >= 0) {
char buf[32] = {};
log::Stream s(buf);
if (client->m_SoftwareVersion) {
log::Stream s(buf);
s << client->software_name() << " v" << (client->m_SoftwareVersion >> 16) << '.' << (client->m_SoftwareVersion & 0xFFFF);
}
LOGINFO(0, (client->m_isIncoming ? "I\t" : "O\t")
@@ -1027,6 +1045,16 @@ int P2PServer::deserialize_block(const uint8_t* buf, uint32_t size, bool compact
return result;
}
const PoolBlock* P2PServer::find_block(const hash& id) const
{
return m_pool->side_chain().find_block(id);
}
const char* P2PServer::get_log_category() const
{
return log_category_prefix;
}
void P2PServer::on_timer()
{
if (m_pool->stopped()) {
@@ -1045,7 +1073,7 @@ void P2PServer::on_timer()
update_peer_list();
save_peer_list_async();
update_peer_connections();
check_zmq();
check_host();
check_block_template();
api_update_local_stats();
}
@@ -1092,12 +1120,13 @@ void P2PServer::download_missing_blocks()
return;
}
std::vector<hash> missing_blocks;
unordered_set<hash> missing_blocks;
m_pool->side_chain().get_missing_blocks(missing_blocks);
if (missing_blocks.empty()) {
m_lookForMissingBlocks = false;
m_missingBlockRequests.clear();
m_blockNotifyRequests.clear();
return;
}
@@ -1124,8 +1153,12 @@ void P2PServer::download_missing_blocks()
for (const hash& id : missing_blocks) {
P2PClient* client = clients[get_random64() % clients.size()];
const uint64_t truncated_block_id = *reinterpret_cast<const uint64_t*>(id.h);
if (!m_missingBlockRequests.insert({ client->m_peerId, truncated_block_id }).second) {
if (client->m_blockPendingRequests.size() >= 25) {
// Too many pending requests to this peer
continue;
}
if (!m_missingBlockRequests.emplace(client->m_peerId, *id.u64()).second) {
// We already asked this peer about this block
// Don't try to ask another peer, leave it for another timer tick
continue;
@@ -1143,7 +1176,7 @@ void P2PServer::download_missing_blocks()
const bool result = send(client,
[&id, client](uint8_t* buf, size_t buf_size) -> size_t
{
LOGINFO(5, "sending BLOCK_REQUEST for id = " << id << " to " << static_cast<char*>(client->m_addrString));
LOGINFO(5, "[download_missing_blocks] sending BLOCK_REQUEST for id = " << id << " to " << static_cast<char*>(client->m_addrString));
if (buf_size < 1 + HASH_SIZE) {
return 0;
@@ -1160,30 +1193,46 @@ void P2PServer::download_missing_blocks()
});
if (result) {
client->m_blockPendingRequests.push_back(id);
client->m_blockPendingRequests.push_back(*id.u64());
}
}
}
void P2PServer::check_zmq()
void P2PServer::check_host()
{
if ((m_timerCounter % 30) != 3) {
if (!m_pool->startup_finished()) {
return;
}
if (!m_pool->zmq_running()) {
LOGERR(1, "ZMQ is not running, restarting it");
m_pool->restart_zmq();
m_pool->reconnect_to_host();
return;
}
const uint64_t height = m_pool->miner_data().height;
const SideChain& side_chain = m_pool->side_chain();
// If the latest 5 side chain blocks are 2 or more Monero blocks ahead, then the node is probably stuck
uint32_t counter = 5;
for (const PoolBlock* b = side_chain.chainTip(); b && (b->m_txinGenHeight >= height + 2); b = side_chain.find_block(b->m_parent)) {
if (--counter == 0) {
const Params::Host& host = m_pool->current_host();
LOGERR(1, host.m_displayName << " seems to be stuck, reconnecting");
m_pool->reconnect_to_host();
return;
}
}
const uint64_t cur_time = seconds_since_epoch();
const uint64_t last_active = m_pool->zmq_last_active();
// If there were no ZMQ messages in the last 5 minutes, then the node is probably stuck
if (cur_time >= last_active + 300) {
const uint64_t dt = static_cast<uint64_t>(cur_time - last_active);
LOGERR(1, "no ZMQ messages received from monerod in the last " << dt << " seconds, check your monerod/p2pool/network/firewall setup!!!");
m_pool->restart_zmq();
const Params::Host& host = m_pool->current_host();
LOGERR(1, "no ZMQ messages received from " << host.m_displayName << " in the last " << dt << " seconds, check your monerod/p2pool/network/firewall setup!!!");
m_pool->reconnect_to_host();
}
}
@@ -1211,8 +1260,7 @@ P2PServer::P2PClient::P2PClient()
, m_handshakeComplete(false)
, m_handshakeInvalid(false)
, m_listenPort(-1)
, m_fastPeerListRequestCount(0)
, m_prevIncomingPeerListRequest(0)
, m_prevPeersSent(0)
, m_nextOutgoingPeerListRequest(0)
, m_lastPeerListRequestTime{}
, m_peerListPendingRequests(0)
@@ -1224,12 +1272,15 @@ P2PServer::P2PClient::P2PClient()
, m_lastBroadcastTimestamp(0)
, m_lastBlockrequestTimestamp(0)
, m_broadcastedHashes{}
, m_broadcastedHashesIndex(0)
{
m_p2pReadBuf[0] = '\0';
}
void P2PServer::on_shutdown()
{
save_peer_list();
uv_timer_stop(&m_timer);
uv_close(reinterpret_cast<uv_handle_t*>(&m_timer), nullptr);
uv_close(reinterpret_cast<uv_handle_t*>(&m_broadcastAsync), nullptr);
@@ -1311,8 +1362,7 @@ void P2PServer::P2PClient::reset()
m_handshakeComplete = false;
m_handshakeInvalid = false;
m_listenPort = -1;
m_fastPeerListRequestCount = 0;
m_prevIncomingPeerListRequest = 0;
m_prevPeersSent = 0;
m_nextOutgoingPeerListRequest = 0;
m_lastPeerListRequestTime = {};
m_peerListPendingRequests = 0;
@@ -1384,7 +1434,14 @@ bool P2PServer::P2PClient::on_read(char* data, uint32_t size)
uint32_t bytes_read;
do {
MessageId id = static_cast<MessageId>(buf[0]);
if (buf[0] > static_cast<uint8_t>(MessageId::LAST)) {
LOGWARN(5, "peer " << static_cast<char*>(m_addrString) << " sent an unknown message id " << buf[0]);
ban(DEFAULT_BAN_TIME);
server->remove_peer_from_list(this);
return false;
}
const MessageId id = static_cast<MessageId>(buf[0]);
// Peer must complete the handshake challenge before sending any other messages
if (!m_handshakeComplete && (id != m_expectedMessage)) {
@@ -1494,7 +1551,7 @@ bool P2PServer::P2PClient::on_read(char* data, uint32_t size)
if (bytes_left >= 1 + sizeof(uint32_t) + block_size) {
bytes_read = 1 + sizeof(uint32_t) + block_size;
const hash expected_id = m_blockPendingRequests.front();
const uint64_t expected_id = m_blockPendingRequests.front();
m_blockPendingRequests.pop_front();
if (!on_block_response(buf + 1 + sizeof(uint32_t), block_size, expected_id)) {
@@ -1569,6 +1626,15 @@ bool P2PServer::P2PClient::on_read(char* data, uint32_t size)
}
}
break;
case MessageId::BLOCK_NOTIFY:
LOGINFO(6, "peer " << log::Gray() << static_cast<char*>(m_addrString) << log::NoColor() << " sent BLOCK_NOTIFY");
if (bytes_left >= 1 + HASH_SIZE) {
bytes_read = 1 + HASH_SIZE;
on_block_notify(buf + 1);
}
break;
}
if (bytes_read) {
@@ -1715,7 +1781,7 @@ void P2PServer::P2PClient::send_handshake_solution(const uint8_t (&challenge)[CH
return;
}
const uint64_t* value = reinterpret_cast<uint64_t*>(work->solution.h);
const uint64_t* value = work->solution.u64();
uint64_t high;
umul128(value[HASH_SIZE / sizeof(uint64_t) - 1], CHALLENGE_DIFFICULTY, &high);
@@ -1861,7 +1927,7 @@ bool P2PServer::P2PClient::on_handshake_solution(const uint8_t* buf)
// Check that incoming connection provided enough PoW
if (m_isIncoming) {
const uint64_t* value = reinterpret_cast<uint64_t*>(solution.h);
const uint64_t* value = solution.u64();
uint64_t high;
umul128(value[HASH_SIZE / sizeof(uint64_t) - 1], CHALLENGE_DIFFICULTY, &high);
@@ -1918,11 +1984,11 @@ void P2PServer::P2PClient::on_after_handshake(uint8_t* &p)
LOGINFO(5, "sending BLOCK_REQUEST for the chain tip to " << static_cast<char*>(m_addrString));
*(p++) = static_cast<uint8_t>(MessageId::BLOCK_REQUEST);
hash empty;
memcpy(p, empty.h, HASH_SIZE);
hash zero_hash;
memcpy(p, zero_hash.h, HASH_SIZE);
p += HASH_SIZE;
m_blockPendingRequests.push_back(empty);
m_blockPendingRequests.push_back(0);
m_lastBroadcastTimestamp = seconds_since_epoch();
}
@@ -1950,14 +2016,32 @@ bool P2PServer::P2PClient::on_block_request(const uint8_t* buf)
memcpy(id.h, buf, HASH_SIZE);
P2PServer* server = static_cast<P2PServer*>(m_owner);
const SideChain& sidechain = server->m_pool->side_chain();
std::vector<uint8_t> blob;
if (!server->m_pool->side_chain().get_block_blob(id, blob) && !id.empty()) {
const PoolBlock* block = sidechain.get_block_blob(id, blob);
if (!block && !id.empty()) {
LOGWARN(5, "got a request for block with id " << id << " but couldn't find it");
}
// Notifications about parent and uncle blocks to speed up syncing
std::vector<hash> notify_blocks;
if (block && (m_protocolVersion >= PROTOCOL_VERSION_1_2)) {
notify_blocks.reserve(block->m_uncles.size() + 2);
notify_blocks.push_back(block->m_parent);
notify_blocks.insert(notify_blocks.end(), block->m_uncles.begin(), block->m_uncles.end());
block = sidechain.find_block(block->m_parent);
if (block) {
notify_blocks.push_back(block->m_parent);
}
}
return server->send(this,
[this, &blob](uint8_t* buf, size_t buf_size) -> size_t
[this, &blob, &notify_blocks](uint8_t* buf, size_t buf_size) -> size_t
{
LOGINFO(5, "sending BLOCK_RESPONSE to " << static_cast<char*>(m_addrString));
@@ -1969,6 +2053,17 @@ bool P2PServer::P2PClient::on_block_request(const uint8_t* buf)
uint8_t* p = buf;
if (buf_size >= 1 + sizeof(uint32_t) + len + notify_blocks.size() * (1 + HASH_SIZE)) {
for (const hash& id : notify_blocks) {
LOGINFO(6, "sending BLOCK_NOTIFY for " << id << " to " << static_cast<char*>(m_addrString));
*(p++) = static_cast<uint8_t>(MessageId::BLOCK_NOTIFY);
memcpy(p, id.h, HASH_SIZE);
p += HASH_SIZE;
}
}
*(p++) = static_cast<uint8_t>(MessageId::BLOCK_RESPONSE);
memcpy(p, &len, sizeof(uint32_t));
@@ -1983,14 +2078,14 @@ bool P2PServer::P2PClient::on_block_request(const uint8_t* buf)
});
}
bool P2PServer::P2PClient::on_block_response(const uint8_t* buf, uint32_t size, const hash& expected_id)
bool P2PServer::P2PClient::on_block_response(const uint8_t* buf, uint32_t size, uint64_t expected_id)
{
P2PServer* server = static_cast<P2PServer*>(m_owner);
const uint64_t cur_time = seconds_since_epoch();
if (!size) {
LOGINFO(5, "peer " << log::Gray() << static_cast<char*>(m_addrString) << log::NoColor() << " sent an empty block response");
if (expected_id.empty() && (cur_time >= m_nextOutgoingPeerListRequest)) {
if ((expected_id == 0) && (cur_time >= m_nextOutgoingPeerListRequest)) {
server->send_peer_list_request(this, cur_time);
}
return true;
@@ -2009,7 +2104,7 @@ bool P2PServer::P2PClient::on_block_response(const uint8_t* buf, uint32_t size,
const PoolBlock* block = server->get_block();
// Chain tip request
if (expected_id.empty()) {
if (expected_id == 0) {
const uint64_t peer_height = block->m_txinGenHeight;
const uint64_t our_height = server->m_pool->miner_data().height;
@@ -2018,12 +2113,15 @@ bool P2PServer::P2PClient::on_block_response(const uint8_t* buf, uint32_t size,
return false;
}
m_broadcastMaxHeight = std::max(m_broadcastMaxHeight, block->m_sidechainHeight);
m_broadcastedHashes[m_broadcastedHashesIndex++ % array_size(&P2PClient::m_broadcastedHashes)] = block->m_sidechainId;
if (cur_time >= m_nextOutgoingPeerListRequest) {
server->send_peer_list_request(this, cur_time);
}
}
else if (block->m_sidechainId != expected_id) {
LOGWARN(3, "peer " << static_cast<char*>(m_addrString) << " sent a wrong block: expected " << expected_id << ", got " << block->m_sidechainId);
else if (*block->m_sidechainId.u64() != expected_id) {
LOGWARN(3, "peer " << static_cast<char*>(m_addrString) << " sent a wrong block: expected " << log::hex_buf(&expected_id) << ", got " << block->m_sidechainId);
return false;
}
@@ -2055,7 +2153,7 @@ bool P2PServer::P2PClient::on_block_broadcast(const uint8_t* buf, uint32_t size,
const PoolBlock* block = server->get_block();
m_broadcastMaxHeight = std::max(m_broadcastMaxHeight, block->m_sidechainHeight);
m_broadcastedHashes[m_broadcastedHashesIndex.fetch_add(1) % array_size(&P2PClient::m_broadcastedHashes)] = block->m_sidechainId;
m_broadcastedHashes[m_broadcastedHashesIndex++ % array_size(&P2PClient::m_broadcastedHashes)] = block->m_sidechainId;
MinerData miner_data = server->m_pool->miner_data();
@@ -2100,46 +2198,40 @@ bool P2PServer::P2PClient::on_peer_list_request(const uint8_t*)
P2PServer* server = static_cast<P2PServer*>(m_owner);
server->check_event_loop_thread(__func__);
const uint64_t cur_time = seconds_since_epoch();
const bool first = (m_prevIncomingPeerListRequest == 0);
// Allow peer list requests no more than once every 30 seconds
if (cur_time - m_prevIncomingPeerListRequest < 30) {
++m_fastPeerListRequestCount;
if (m_fastPeerListRequestCount >= 3) {
LOGWARN(4, "peer " << static_cast<char*>(m_addrString) << " is sending PEER_LIST_REQUEST too often");
return false;
}
}
m_prevIncomingPeerListRequest = cur_time;
Peer peers[PEER_LIST_RESPONSE_MAX_PEERS];
uint32_t num_selected_peers = 0;
// Send every 4th peer on average, selected at random
const uint32_t peers_to_send_target = std::min<uint32_t>(PEER_LIST_RESPONSE_MAX_PEERS, std::max<uint32_t>(1, server->m_numConnections / 4));
uint32_t n = 0;
const uint64_t cur_time = seconds_since_epoch();
const bool first = (m_prevPeersSent == 0);
for (P2PClient* client = static_cast<P2PClient*>(server->m_connectedClientsList->m_next); client != server->m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
if (!client->is_good() || (client->m_addr == m_addr)) {
continue;
}
// Rate limit peer list requests (send an empty response if the request comes too soon)
if (first || (cur_time >= m_prevPeersSent + PEER_REQUEST_DELAY)) {
m_prevPeersSent = cur_time;
const Peer p{ client->m_isV6, client->m_addr, client->m_listenPort, 0, 0 };
++n;
// Send every 4th peer on average, selected at random
const uint32_t peers_to_send_target = std::min<uint32_t>(PEER_LIST_RESPONSE_MAX_PEERS, std::max<uint32_t>(1, server->m_numConnections / 4));
uint32_t n = 0;
// Use https://en.wikipedia.org/wiki/Reservoir_sampling algorithm
if (num_selected_peers < peers_to_send_target) {
peers[num_selected_peers++] = p;
continue;
}
for (P2PClient* client = static_cast<P2PClient*>(server->m_connectedClientsList->m_next); client != server->m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
if (!client->is_good() || (client->m_addr == m_addr)) {
continue;
}
uint64_t k;
umul128(server->get_random64(), n, &k);
const Peer p{ client->m_isV6, client->m_addr, client->m_listenPort, 0, 0 };
++n;
if (k < peers_to_send_target) {
peers[k] = p;
// Use https://en.wikipedia.org/wiki/Reservoir_sampling algorithm
if (num_selected_peers < peers_to_send_target) {
peers[num_selected_peers++] = p;
continue;
}
uint64_t k;
umul128(server->get_random64(), n, &k);
if (k < peers_to_send_target) {
peers[k] = p;
}
}
}
@@ -2226,7 +2318,17 @@ void P2PServer::P2PClient::on_peer_list_response(const uint8_t* buf)
// Check for protocol version message
if ((*reinterpret_cast<uint32_t*>(ip.data + 12) == 0xFFFFFFFFU) && (port == 0xFFFF)) {
m_protocolVersion = *reinterpret_cast<uint32_t*>(ip.data);
const uint32_t version = *reinterpret_cast<uint32_t*>(ip.data);
// Clients with different major protocol versions communicate using v1.0 protocol
// to reduce backwards compatibility requirements for newer clients
if ((version >> 16) != (SUPPORTED_PROTOCOL_VERSION >> 16)) {
m_protocolVersion = PROTOCOL_VERSION_1_0;
}
else {
m_protocolVersion = std::min(version, SUPPORTED_PROTOCOL_VERSION);
}
m_SoftwareVersion = *reinterpret_cast<uint32_t*>(ip.data + 4);
m_SoftwareID = *reinterpret_cast<uint32_t*>(ip.data + 8);
LOGINFO(5, "peer " << log::Gray() << static_cast<char*>(m_addrString) << log::NoColor()
@@ -2258,6 +2360,54 @@ void P2PServer::P2PClient::on_peer_list_response(const uint8_t* buf)
}
}
void P2PServer::P2PClient::on_block_notify(const uint8_t* buf)
{
hash id;
memcpy(id.h, buf, HASH_SIZE);
m_broadcastedHashes[m_broadcastedHashesIndex++ % array_size(&P2PClient::m_broadcastedHashes)] = id;
P2PServer* server = static_cast<P2PServer*>(m_owner);
// If we don't know about this block, request it from this peer. The peer can do it to speed up our initial sync, for example.
if (!server->find_block(id)) {
LOGINFO(6, "Received an unknown block " << id << " in BLOCK_NOTIFY");
if (m_blockPendingRequests.size() >= 25) {
LOGINFO(5, "Too many pending block requests, ignoring it");
return;
}
if (!server->m_blockNotifyRequests.insert(*id.u64()).second || !server->m_missingBlockRequests.emplace(m_peerId, *id.u64()).second) {
LOGINFO(6, "BLOCK_REQUEST for id = " << id << " was already sent");
return;
}
const bool result = server->send(this,
[&id, this](uint8_t* buf, size_t buf_size) -> size_t
{
LOGINFO(5, "[on_block_notify] sending BLOCK_REQUEST for id = " << id << " to " << static_cast<char*>(m_addrString));
if (buf_size < 1 + HASH_SIZE) {
return 0;
}
uint8_t* p = buf;
*(p++) = static_cast<uint8_t>(MessageId::BLOCK_REQUEST);
memcpy(p, id.h, HASH_SIZE);
p += HASH_SIZE;
return p - buf;
});
if (result) {
m_blockPendingRequests.push_back(*id.u64());
}
}
}
bool P2PServer::P2PClient::handle_incoming_block_async(const PoolBlock* block, uint64_t max_time_delta)
{
P2PServer* server = static_cast<P2PServer*>(m_owner);
@@ -2339,7 +2489,7 @@ bool P2PServer::P2PClient::handle_incoming_block_async(const PoolBlock* block, u
[](uv_work_t* req, int /*status*/)
{
Work* work = reinterpret_cast<Work*>(req->data);
work->client->post_handle_incoming_block(work->client_reset_counter, work->missing_blocks);
work->client->post_handle_incoming_block(work->block, work->client_reset_counter, work->missing_blocks);
delete work;
BACKGROUND_JOB_STOP(P2PServer::handle_incoming_block_async);
});
@@ -2362,8 +2512,7 @@ void P2PServer::P2PClient::handle_incoming_block(p2pool* pool, PoolBlock& block,
LOGWARN(3, "peer " << static_cast<char*>(m_addrString) << " banned for " << DEFAULT_BAN_TIME << " seconds");
}
else {
const log::hex_buf addr_hex(addr.data, sizeof(addr.data));
LOGWARN(3, "IP " << addr_hex << " banned for " << DEFAULT_BAN_TIME << " seconds");
LOGWARN(3, addr << " banned for " << DEFAULT_BAN_TIME << " seconds");
}
P2PServer* server = pool->p2p_server();
@@ -2372,7 +2521,7 @@ void P2PServer::P2PClient::handle_incoming_block(p2pool* pool, PoolBlock& block,
}
}
void P2PServer::P2PClient::post_handle_incoming_block(const uint32_t reset_counter, std::vector<hash>& missing_blocks)
void P2PServer::P2PClient::post_handle_incoming_block(const PoolBlock& block, const uint32_t reset_counter, std::vector<hash>& missing_blocks)
{
// We might have been disconnected while side_chain was adding the block
// In this case we can't send BLOCK_REQUEST messages on this connection anymore
@@ -2386,11 +2535,14 @@ void P2PServer::P2PClient::post_handle_incoming_block(const uint32_t reset_count
P2PServer* server = static_cast<P2PServer*>(m_owner);
// If the initial sync is not finished yet, try to ask the fastest peer too
P2PClient* c = server->m_fastestPeer;
if (c && (c != this) && !server->m_pool->side_chain().precalcFinished()) {
LOGINFO(5, "peer " << static_cast<char*>(c->m_addrString) << " is faster, sending BLOCK_REQUEST to it too");
c->post_handle_incoming_block(c->m_resetCounter.load(), missing_blocks);
// If the initial sync is not finished yet, try to ask the fastest peer instead
if (!server->m_pool->side_chain().precalcFinished()) {
P2PClient* c = server->m_fastestPeer;
if (c && (c != this) && (c->m_broadcastMaxHeight >= block.m_sidechainHeight)) {
LOGINFO(5, "peer " << static_cast<char*>(c->m_addrString) << " is faster, sending BLOCK_REQUEST to it instead");
c->post_handle_incoming_block(block, c->m_resetCounter.load(), missing_blocks);
return;
}
}
ReadLock lock(server->m_cachedBlocksLock);
@@ -2405,10 +2557,14 @@ void P2PServer::P2PClient::post_handle_incoming_block(const uint32_t reset_count
}
}
if (!server->m_missingBlockRequests.emplace(m_peerId, *id.u64()).second) {
continue;
}
const bool result = server->send(this,
[this, &id](uint8_t* buf, size_t buf_size) -> size_t
{
LOGINFO(5, "sending BLOCK_REQUEST for id = " << id << " to " << static_cast<char*>(m_addrString));
LOGINFO(5, "[post_handle_incoming_block] sending BLOCK_REQUEST for id = " << id << " to " << static_cast<char*>(m_addrString));
if (buf_size < 1 + HASH_SIZE) {
return 0;
@@ -2428,7 +2584,7 @@ void P2PServer::P2PClient::post_handle_incoming_block(const uint32_t reset_count
return;
}
m_blockPendingRequests.push_back(id);
m_blockPendingRequests.push_back(*id.u64());
}
}
+25 -19
View File
@@ -19,7 +19,7 @@
#include "tcp_server.h"
#include "pool_block.h"
#include <list>
#include <deque>
namespace p2pool {
@@ -37,22 +37,25 @@ static constexpr int DEFAULT_P2P_PORT_MINI = 37888;
static constexpr uint32_t PROTOCOL_VERSION_1_0 = 0x00010000UL;
static constexpr uint32_t PROTOCOL_VERSION_1_1 = 0x00010001UL;
static constexpr uint32_t PROTOCOL_VERSION_1_2 = 0x00010002UL;
static constexpr uint32_t SUPPORTED_PROTOCOL_VERSION = PROTOCOL_VERSION_1_1;
static constexpr uint32_t SUPPORTED_PROTOCOL_VERSION = PROTOCOL_VERSION_1_2;
class P2PServer : public TCPServer
{
public:
enum class MessageId {
HANDSHAKE_CHALLENGE = 0,
HANDSHAKE_SOLUTION = 1,
LISTEN_PORT = 2,
BLOCK_REQUEST = 3,
BLOCK_RESPONSE = 4,
BLOCK_BROADCAST = 5,
PEER_LIST_REQUEST = 6,
PEER_LIST_RESPONSE = 7,
BLOCK_BROADCAST_COMPACT = 8,
HANDSHAKE_CHALLENGE,
HANDSHAKE_SOLUTION,
LISTEN_PORT,
BLOCK_REQUEST,
BLOCK_RESPONSE,
BLOCK_BROADCAST,
PEER_LIST_REQUEST,
PEER_LIST_RESPONSE,
BLOCK_BROADCAST_COMPACT,
BLOCK_NOTIFY,
LAST = BLOCK_NOTIFY,
};
explicit P2PServer(p2pool *pool);
@@ -105,14 +108,15 @@ public:
void on_after_handshake(uint8_t* &p);
bool on_listen_port(const uint8_t* buf);
bool on_block_request(const uint8_t* buf);
bool on_block_response(const uint8_t* buf, uint32_t size, const hash& expected_id);
bool on_block_response(const uint8_t* buf, uint32_t size, uint64_t expected_id);
bool on_block_broadcast(const uint8_t* buf, uint32_t size, bool compact);
bool on_peer_list_request(const uint8_t* buf);
void on_peer_list_response(const uint8_t* buf);
void on_block_notify(const uint8_t* buf);
bool handle_incoming_block_async(const PoolBlock* block, uint64_t max_time_delta = 0);
void handle_incoming_block(p2pool* pool, PoolBlock& block, const uint32_t reset_counter, bool is_v6, const raw_ip& addr, std::vector<hash>& missing_blocks);
void post_handle_incoming_block(const uint32_t reset_counter, std::vector<hash>& missing_blocks);
void post_handle_incoming_block(const PoolBlock& block, const uint32_t reset_counter, std::vector<hash>& missing_blocks);
bool is_good() const { return m_handshakeComplete && !m_handshakeInvalid && (m_listenPort >= 0); }
@@ -131,8 +135,7 @@ public:
bool m_handshakeInvalid;
int m_listenPort;
uint32_t m_fastPeerListRequestCount;
uint64_t m_prevIncomingPeerListRequest;
uint64_t m_prevPeersSent;
uint64_t m_nextOutgoingPeerListRequest;
std::chrono::high_resolution_clock::time_point m_lastPeerListRequestTime;
int m_peerListPendingRequests;
@@ -143,14 +146,14 @@ public:
int64_t m_pingTime;
std::list<hash> m_blockPendingRequests;
std::deque<uint64_t> m_blockPendingRequests;
uint64_t m_lastAlive;
uint64_t m_lastBroadcastTimestamp;
uint64_t m_lastBlockrequestTimestamp;
hash m_broadcastedHashes[8];
std::atomic<uint32_t> m_broadcastedHashesIndex{ 0 };
uint32_t m_broadcastedHashesIndex;
};
void broadcast(const PoolBlock& block, const PoolBlock* parent);
@@ -172,8 +175,10 @@ public:
int deserialize_block(const uint8_t* buf, uint32_t size, bool compact, uint64_t received_timestamp);
const PoolBlock* get_block() const { return m_block; }
const PoolBlock* find_block(const hash& id) const;
private:
const char* get_category() const override { return "P2PServer "; }
const char* get_log_category() const override;
p2pool* m_pool;
BlockCache* m_cache;
@@ -191,7 +196,7 @@ private:
void flush_cache();
void download_missing_blocks();
void check_zmq();
void check_host();
void check_block_template();
void update_peer_connections();
void update_peer_list();
@@ -249,6 +254,7 @@ private:
bool m_lookForMissingBlocks;
unordered_set<std::pair<uint64_t, uint64_t>> m_missingBlockRequests;
unordered_set<uint64_t> m_blockNotifyRequests;
P2PClient* m_fastestPeer;
+156 -93
View File
@@ -40,7 +40,8 @@
#include <fstream>
#include <numeric>
constexpr char log_category_prefix[] = "P2Pool ";
LOG_CATEGORY(P2Pool)
constexpr int BLOCK_HEADERS_REQUIRED = 720;
constexpr uint64_t SEEDHASH_EPOCH_BLOCKS = 2048;
@@ -69,36 +70,15 @@ p2pool::p2pool(int argc, char* argv[])
}
#endif
if (!p->m_wallet.valid()) {
LOGERR(1, "Invalid wallet address. Try \"p2pool --help\".");
throw std::exception();
}
m_hostStr = p->m_host;
if (p->m_socks5Proxy.empty()) {
if (p->m_dns) {
bool is_v6;
if (!resolve_host(p->m_host, is_v6)) {
LOGERR(1, "resolve_host failed for " << p->m_host);
throw std::exception();
}
}
else if (p->m_host.find_first_not_of("0123456789.:") != std::string::npos) {
LOGERR(1, "Can't resolve hostname " << p->m_host << " with DNS disabled");
for (Params::Host& h : p->m_hosts) {
if (!h.init_display_name(*p)) {
throw std::exception();
}
}
{
const bool changed = (p->m_host != m_hostStr);
const std::string rpc_port = ':' + std::to_string(p->m_rpcPort);
const std::string zmq_port = ":ZMQ:" + std::to_string(p->m_zmqPort);
m_hostStr += rpc_port + zmq_port;
if (changed) {
m_hostStr += " (" + p->m_host + ')';
}
}
m_currentHostIndex = 0;
m_hostPing.resize(p->m_hosts.size());
hash pub, sec, eph_public_key;
generate_keys(pub, sec);
@@ -139,15 +119,16 @@ p2pool::p2pool(int argc, char* argv[])
}
m_stopAsync.data = this;
err = uv_async_init(uv_default_loop_checked(), &m_restartZMQAsync, on_restart_zmq);
err = uv_async_init(uv_default_loop_checked(), &m_reconnectToHostAsync, on_reconnect_to_host);
if (err) {
LOGERR(1, "uv_async_init failed, error " << uv_err_name(err));
throw std::exception();
}
m_restartZMQAsync.data = this;
m_reconnectToHostAsync.data = this;
uv_rwlock_init_checked(&m_mainchainLock);
uv_rwlock_init_checked(&m_minerDataLock);
uv_rwlock_init_checked(&m_ZMQReaderLock);
uv_mutex_init_checked(&m_foundBlocksLock);
#ifdef WITH_RANDOMX
uv_mutex_init_checked(&m_minerLock);
@@ -206,6 +187,7 @@ p2pool::~p2pool()
uv_rwlock_destroy(&m_mainchainLock);
uv_rwlock_destroy(&m_minerDataLock);
uv_rwlock_destroy(&m_ZMQReaderLock);
uv_mutex_destroy(&m_foundBlocksLock);
#ifdef WITH_RANDOMX
uv_mutex_destroy(&m_minerLock);
@@ -220,6 +202,47 @@ p2pool::~p2pool()
delete m_params;
}
void p2pool::update_host_ping(const std::string& display_name, double ping)
{
if (ping < 100) {
LOGINFO(1, display_name << " ping is " << ping << " ms");
}
else {
LOGWARN(1, display_name << " ping is " << ping << " ms, this is too high for an efficient mining. Try to use a different node, or your own local node.");
}
const std::vector<Params::Host>& v = m_params->m_hosts;
for (size_t i = 0, n = v.size(); i < n; ++i) {
if (v[i].m_displayName == display_name) {
m_hostPing[i] = ping;
return;
}
}
}
void p2pool::print_hosts() const
{
const Params::Host& host = current_host();
for (size_t i = 0, n = m_params->m_hosts.size(); i < n; ++i) {
const Params::Host& h = m_params->m_hosts[i];
char buf[64] = {};
if (m_hostPing[i] > 0.0) {
log::Stream s(buf);
s << " (" << m_hostPing[i] << " ms)";
}
if (h.m_displayName == host.m_displayName) {
LOGINFO(0, log::LightCyan() << "-> " << h.m_displayName << static_cast<const char*>(buf));
}
else {
LOGINFO(0, " " << h.m_displayName << static_cast<const char*>(buf));
}
}
}
bool p2pool::calculate_hash(const void* data, size_t size, uint64_t height, const hash& seed, hash& result, bool force_light_mode)
{
return m_hasher->calculate(data, size, height, seed, result, force_light_mode);
@@ -297,17 +320,15 @@ void p2pool::handle_miner_data(MinerData& data)
{
WriteLock lock(m_mainchainLock);
m_mainchainByHeight[data.height].difficulty = data.difficulty;
ChainMain& c0 = m_mainchainByHeight[data.height];
c0.height = data.height;
c0.difficulty = data.difficulty;
ChainMain& c = m_mainchainByHeight[data.height - 1];
c.height = data.height - 1;
c.id = data.prev_id;
ChainMain& c1 = m_mainchainByHeight[data.height - 1];
c1.height = data.height - 1;
c1.id = data.prev_id;
// timestamp and reward is unknown here
c.timestamp = 0;
c.reward = 0;
m_mainchainByHash[c.id] = c;
m_mainchainByHash[c1.id] = c1;
cleanup_mainchain_data(data.height);
}
@@ -321,8 +342,11 @@ void p2pool::handle_miner_data(MinerData& data)
m_updateSeed = true;
update_median_timestamp();
const Params::Host& host = current_host();
LOGINFO(2,
"new miner data\n---------------------------------------------------------------------------------------------------------------" <<
"\nhost = " << host.m_displayName <<
"\nmajor_version = " << data.major_version <<
"\nheight = " << data.height <<
"\nprev_id = " << log::LightBlue() << data.prev_id << log::NoColor() <<
@@ -370,15 +394,15 @@ void p2pool::handle_miner_data(MinerData& data)
log::Stream s(buf);
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_header_by_height\",\"params\":{\"height\":" << h << "}}\0";
JSONRPCRequest::call(m_params->m_host, m_params->m_rpcPort, buf, m_params->m_rpcLogin, m_params->m_socks5Proxy,
[this, h](const char* data, size_t size)
JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params->m_socks5Proxy,
[this, h](const char* data, size_t size, double)
{
ChainMain block;
if (!parse_block_header(data, size, block)) {
LOGERR(1, "couldn't download block header for height " << h);
}
},
[h](const char* data, size_t size)
[h](const char* data, size_t size, double)
{
if (size > 0) {
LOGERR(1, "couldn't download block header for height " << h << ", error " << log::const_buf(data, size));
@@ -528,7 +552,7 @@ void p2pool::on_stop(uv_async_t* async)
uv_close(reinterpret_cast<uv_handle_t*>(&pool->m_submitBlockAsync), nullptr);
uv_close(reinterpret_cast<uv_handle_t*>(&pool->m_blockTemplateAsync), nullptr);
uv_close(reinterpret_cast<uv_handle_t*>(&pool->m_stopAsync), nullptr);
uv_close(reinterpret_cast<uv_handle_t*>(&pool->m_restartZMQAsync), nullptr);
uv_close(reinterpret_cast<uv_handle_t*>(&pool->m_reconnectToHostAsync), nullptr);
init_signals(pool, false);
@@ -603,11 +627,13 @@ void p2pool::submit_block() const
}
request.append("\"]}");
JSONRPCRequest::call(m_params->m_host, m_params->m_rpcPort, request, m_params->m_rpcLogin, m_params->m_socks5Proxy,
[height, diff, template_id, nonce, extra_nonce, sidechain_id, is_external](const char* data, size_t size)
const Params::Host& host = current_host();
JSONRPCRequest::call(host.m_address, host.m_rpcPort, request, host.m_rpcLogin, m_params->m_socks5Proxy,
[height, diff, template_id, nonce, extra_nonce, sidechain_id, is_external](const char* data, size_t size, double)
{
rapidjson::Document doc;
if (doc.Parse<rapidjson::kParseCommentsFlag | rapidjson::kParseTrailingCommasFlag>(data, size).HasParseError() || !doc.IsObject()) {
if (doc.Parse(data, size).HasParseError() || !doc.IsObject()) {
LOGERR(0, "submit_block: invalid JSON response from daemon");
return;
}
@@ -648,7 +674,7 @@ void p2pool::submit_block() const
LOGWARN(0, "submit_block: daemon sent unrecognizable reply: " << log::const_buf(data, size));
},
[is_external](const char* data, size_t size)
[is_external](const char* data, size_t size, double)
{
if (size > 0) {
if (is_external) {
@@ -714,14 +740,16 @@ void p2pool::download_block_headers(uint64_t current_height)
char buf[log::Stream::BUF_SIZE + 1] = {};
log::Stream s(buf);
const Params::Host& host = current_host();
// First download 2 RandomX seeds
const uint64_t seed_heights[2] = { prev_seed_height, seed_height };
for (uint64_t height : seed_heights) {
s.m_pos = 0;
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_header_by_height\",\"params\":{\"height\":" << height << "}}\0";
JSONRPCRequest::call(m_params->m_host, m_params->m_rpcPort, buf, m_params->m_rpcLogin, m_params->m_socks5Proxy,
[this, prev_seed_height, height](const char* data, size_t size)
JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params->m_socks5Proxy,
[this, prev_seed_height, height](const char* data, size_t size, double)
{
ChainMain block;
if (parse_block_header(data, size, block)) {
@@ -735,7 +763,7 @@ void p2pool::download_block_headers(uint64_t current_height)
PANIC_STOP();
}
},
[height](const char* data, size_t size)
[height](const char* data, size_t size, double)
{
if (size > 0) {
LOGERR(1, "fatal error: couldn't download block header for seed height " << height << ", error " << log::const_buf(data, size));
@@ -749,8 +777,8 @@ void p2pool::download_block_headers(uint64_t current_height)
s.m_pos = 0;
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_headers_range\",\"params\":{\"start_height\":" << start_height << ",\"end_height\":" << current_height - 1 << "}}\0";
JSONRPCRequest::call(m_params->m_host, m_params->m_rpcPort, buf, m_params->m_rpcLogin, m_params->m_socks5Proxy,
[this, start_height, current_height](const char* data, size_t size)
JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params->m_socks5Proxy,
[this, start_height, current_height, host](const char* data, size_t size, double)
{
if (parse_block_headers_range(data, size) == current_height - start_height) {
update_median_timestamp();
@@ -762,15 +790,33 @@ void p2pool::download_block_headers(uint64_t current_height)
start_mining(m_params->m_minerThreads);
}
#endif
try {
m_ZMQReader = new ZMQReader(m_params->m_host, m_params->m_zmqPort, m_params->m_socks5Proxy, this);
}
catch (const std::exception& e) {
LOGERR(1, "Couldn't start ZMQ reader: exception " << e.what());
PANIC_STOP();
{
WriteLock lock(m_ZMQReaderLock);
try {
m_ZMQReader = new ZMQReader(host.m_address, host.m_zmqPort, m_params->m_socks5Proxy, this);
m_zmqLastActive = seconds_since_epoch();
}
catch (const std::exception& e) {
LOGERR(1, "Couldn't start ZMQ reader: exception " << e.what());
PANIC_STOP();
}
}
api_update_network_stats();
get_miner_data();
// Get ping times for all other hosts
for (const Params::Host& h : m_params->m_hosts) {
const std::string& name = h.m_displayName;
if (name != host.m_displayName) {
JSONRPCRequest::call(h.m_address, h.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_version\"}", h.m_rpcLogin, m_params->m_socks5Proxy,
[this, name](const char*, size_t, double tcp_ping) { update_host_ping(name, tcp_ping); },
[](const char*, size_t, double) {});
}
}
m_startupFinished = true;
}
}
else {
@@ -778,7 +824,7 @@ void p2pool::download_block_headers(uint64_t current_height)
download_block_headers(current_height);
}
},
[this, start_height, current_height](const char* data, size_t size)
[this, start_height, current_height](const char* data, size_t size, double)
{
if (size > 0) {
LOGERR(1, "Couldn't download block headers for heights " << start_height << " - " << current_height - 1 << ", error " << log::const_buf(data, size));
@@ -804,13 +850,13 @@ bool p2pool::get_timestamps(uint64_t (&timestamps)[TIMESTAMP_WINDOW]) const
{
ReadLock lock(m_mainchainLock);
if (m_mainchainByHeight.size() <= TIMESTAMP_WINDOW) {
if (m_mainchainByHeight.size() < TIMESTAMP_WINDOW) {
return false;
}
auto it = m_mainchainByHeight.end();
for (int i = 0; (i < TIMESTAMP_WINDOW) && (it != m_mainchainByHeight.begin()); ++i) {
for (int i = 0; i < TIMESTAMP_WINDOW; ++i) {
--it;
timestamps[i] = it->second.timestamp;
}
@@ -857,17 +903,20 @@ void p2pool::stratum_on_block()
void p2pool::get_info()
{
JSONRPCRequest::call(m_params->m_host, m_params->m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_info\"}", m_params->m_rpcLogin, m_params->m_socks5Proxy,
[this](const char* data, size_t size)
const Params::Host& host = current_host();
JSONRPCRequest::call(host.m_address, host.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_info\"}", host.m_rpcLogin, m_params->m_socks5Proxy,
[this](const char* data, size_t size, double)
{
parse_get_info_rpc(data, size);
},
[this](const char* data, size_t size)
[this, host](const char* data, size_t size, double)
{
if (size > 0) {
LOGWARN(1, "get_info RPC request failed: error " << log::const_buf(data, size) << ", trying again in 1 second");
LOGWARN(1, "get_info RPC request to " << host.m_displayName << " failed: error " << log::const_buf(data, size) << ", trying again in 1 second");
if (!m_stopped) {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
switch_host();
get_info();
}
}
@@ -919,7 +968,7 @@ void p2pool::parse_get_info_rpc(const char* data, size_t size)
}
rapidjson::Document doc;
doc.Parse<rapidjson::kParseCommentsFlag | rapidjson::kParseTrailingCommasFlag>(data, size);
doc.Parse(data, size);
if (!doc.IsObject() || !doc.HasMember("result")) {
LOGWARN(1, "get_info RPC response is invalid (\"result\" not found), trying again in 1 second");
@@ -970,21 +1019,14 @@ void p2pool::parse_get_info_rpc(const char* data, size_t size)
void p2pool::get_version()
{
const uint64_t t1 = microseconds_since_epoch();
const Params::Host& host = current_host();
JSONRPCRequest::call(m_params->m_host, m_params->m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_version\"}", m_params->m_rpcLogin, m_params->m_socks5Proxy,
[this, t1](const char* data, size_t size)
JSONRPCRequest::call(host.m_address, host.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_version\"}", host.m_rpcLogin, m_params->m_socks5Proxy,
[this](const char* data, size_t size, double)
{
const double node_ping = static_cast<double>(microseconds_since_epoch() - t1) / 1e3;
if (node_ping < 100) {
LOGINFO(1, m_hostStr << " ping time is " << node_ping << " ms");
}
else {
LOGWARN(1, m_hostStr << " ping time is " << node_ping << " ms, this is too high for an efficient mining. Try to use a different node, or your own local node.");
}
parse_get_version_rpc(data, size);
},
[this](const char* data, size_t size)
[this](const char* data, size_t size, double)
{
if (size > 0) {
LOGWARN(1, "get_version RPC request failed: error " << log::const_buf(data, size) << ", trying again in 1 second");
@@ -1003,7 +1045,7 @@ void p2pool::parse_get_version_rpc(const char* data, size_t size)
}
rapidjson::Document doc;
doc.Parse<rapidjson::kParseCommentsFlag | rapidjson::kParseTrailingCommasFlag>(data, size);
doc.Parse(data, size);
if (!doc.IsObject() || !doc.HasMember("result")) {
LOGWARN(1, "get_version RPC response is invalid (\"result\" not found), trying again in 1 second");
@@ -1047,24 +1089,28 @@ void p2pool::parse_get_version_rpc(const char* data, size_t size)
get_miner_data();
}
void p2pool::get_miner_data()
void p2pool::get_miner_data(bool retry)
{
if (m_getMinerDataPending) {
return;
}
m_getMinerDataPending = true;
JSONRPCRequest::call(m_params->m_host, m_params->m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_miner_data\"}", m_params->m_rpcLogin, m_params->m_socks5Proxy,
[this](const char* data, size_t size)
const Params::Host& host = current_host();
JSONRPCRequest::call(host.m_address, host.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_miner_data\"}", host.m_rpcLogin, m_params->m_socks5Proxy,
[this, host](const char* data, size_t size, double tcp_ping)
{
parse_get_miner_data_rpc(data, size);
update_host_ping(host.m_displayName, tcp_ping);
},
[this](const char* data, size_t size)
[this, host, retry](const char* data, size_t size, double)
{
if (size > 0) {
LOGWARN(1, "get_miner_data RPC request failed: error " << log::const_buf(data, size) << ", trying again in 1 second");
if (!m_stopped) {
LOGWARN(1, "get_miner_data RPC request to " << host.m_displayName << " failed: error " << log::const_buf(data, size) << (retry ? ", trying again in 1 second" : ""));
if (!m_stopped && retry) {
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
m_getMinerDataPending = false;
get_miner_data();
}
}
@@ -1089,7 +1135,7 @@ void p2pool::parse_get_miner_data_rpc(const char* data, size_t size)
m_getMinerDataHash = h;
rapidjson::Document doc;
doc.Parse<rapidjson::kParseCommentsFlag | rapidjson::kParseTrailingCommasFlag>(data, size);
doc.Parse(data, size);
if (!doc.IsObject() || !doc.HasMember("result")) {
LOGWARN(1, "get_miner_data RPC response is invalid, skipping it");
@@ -1139,7 +1185,7 @@ void p2pool::parse_get_miner_data_rpc(const char* data, size_t size)
bool p2pool::parse_block_header(const char* data, size_t size, ChainMain& c)
{
rapidjson::Document doc;
if (doc.Parse<rapidjson::kParseCommentsFlag | rapidjson::kParseTrailingCommasFlag>(data, size).HasParseError() || !doc.IsObject()) {
if (doc.Parse(data, size).HasParseError() || !doc.IsObject()) {
LOGERR(1, "parse_block_header: invalid JSON response from daemon");
return false;
}
@@ -1181,7 +1227,7 @@ bool p2pool::parse_block_header(const char* data, size_t size, ChainMain& c)
uint32_t p2pool::parse_block_headers_range(const char* data, size_t size)
{
rapidjson::Document doc;
if (doc.Parse<rapidjson::kParseCommentsFlag | rapidjson::kParseTrailingCommasFlag>(data, size).HasParseError() || !doc.IsObject()) {
if (doc.Parse(data, size).HasParseError() || !doc.IsObject()) {
LOGERR(1, "parse_block_headers_range: invalid JSON response from daemon");
return 0;
}
@@ -1573,33 +1619,47 @@ void p2pool::stop()
bool p2pool::zmq_running() const
{
ReadLock lock(m_ZMQReaderLock);
return m_ZMQReader && m_ZMQReader->is_running();
}
void p2pool::restart_zmq()
const Params::Host& p2pool::switch_host()
{
// If p2pool is stopped, m_restartZMQAsync is most likely already closed
const std::vector<Params::Host>& v = m_params->m_hosts;
return v[++m_currentHostIndex % v.size()];
}
void p2pool::reconnect_to_host()
{
// If p2pool is stopped, m_reconnectToHostAsync is most likely already closed
if (m_stopped) {
return;
}
if (!is_main_thread()) {
uv_async_send(&m_restartZMQAsync);
uv_async_send(&m_reconnectToHostAsync);
return;
}
get_miner_data();
const Params::Host& new_host = switch_host();
WriteLock lock(m_ZMQReaderLock);
delete m_ZMQReader;
m_ZMQReader = nullptr;
try {
m_ZMQReader = new ZMQReader(m_params->m_host, m_params->m_zmqPort, m_params->m_socks5Proxy, this);
ZMQReader* new_reader = new ZMQReader(new_host.m_address, new_host.m_zmqPort, m_params->m_socks5Proxy, this);
m_zmqLastActive = seconds_since_epoch();
m_ZMQReader = new_reader;
}
catch (const std::exception& e) {
LOGERR(1, "Couldn't restart ZMQ reader: exception " << e.what());
}
if (m_ZMQReader) {
get_miner_data(false);
}
}
int p2pool::run()
@@ -1624,11 +1684,14 @@ int p2pool::run()
load_found_blocks();
const int rc = uv_run(uv_default_loop_checked(), UV_RUN_DEFAULT);
LOGINFO(1, "uv_run exited, result = " << rc);
WriteLock lock(m_ZMQReaderLock);
delete m_ZMQReader;
m_ZMQReader = nullptr;
}
catch (const std::exception& e) {
const char* s = e.what();
LOGERR(1, "exception " << s);
LOGERR(1, "exception " << e.what());
PANIC_STOP();
}
+24 -7
View File
@@ -18,11 +18,11 @@
#pragma once
#include "uv_util.h"
#include "params.h"
#include <map>
namespace p2pool {
struct Params;
class RandomX_Hasher_Base;
class BlockTemplate;
class Mempool;
@@ -46,11 +46,19 @@ public:
bool stopped() const { return m_stopped; }
void stop();
const std::string& host_str() const { return m_hostStr; }
const Params& params() const { return *m_params; }
BlockTemplate& block_template() { return *m_blockTemplate; }
SideChain& side_chain() { return *m_sideChain; }
FORCEINLINE const Params::Host& current_host() const
{
const std::vector<Params::Host>& v = m_params->m_hosts;
return v[m_currentHostIndex % v.size()];
}
void update_host_ping(const std::string& display_name, double ping);
void print_hosts() const;
FORCEINLINE MinerData miner_data() const
{
ReadLock lock(m_minerDataLock);
@@ -98,23 +106,29 @@ public:
bool zmq_running() const;
uint64_t zmq_last_active() const { return m_zmqLastActive; }
uint64_t start_time() const { return m_startTime; }
void restart_zmq();
void reconnect_to_host();
bool startup_finished() const { return m_startupFinished.load(); }
private:
p2pool(const p2pool&) = delete;
p2pool(p2pool&&) = delete;
const Params::Host& switch_host();
static void on_submit_block(uv_async_t* async) { reinterpret_cast<p2pool*>(async->data)->submit_block(); }
static void on_update_block_template(uv_async_t* async) { reinterpret_cast<p2pool*>(async->data)->update_block_template(); }
static void on_stop(uv_async_t*);
static void on_restart_zmq(uv_async_t* async) { reinterpret_cast<p2pool*>(async->data)->restart_zmq(); }
static void on_reconnect_to_host(uv_async_t* async) { reinterpret_cast<p2pool*>(async->data)->reconnect_to_host(); }
void submit_block() const;
std::atomic<bool> m_stopped;
std::string m_hostStr;
const Params* m_params;
std::vector<double> m_hostPing;
std::atomic<uint32_t> m_currentHostIndex;
p2pool_api* m_api;
SideChain* m_sideChain;
@@ -143,7 +157,7 @@ private:
void get_version();
void parse_get_version_rpc(const char* data, size_t size);
void get_miner_data();
void get_miner_data(bool retry = true);
void parse_get_miner_data_rpc(const char* data, size_t size);
bool parse_block_header(const char* data, size_t size, ChainMain& c);
@@ -179,6 +193,8 @@ private:
StratumServer* m_stratumServer = nullptr;
P2PServer* m_p2pServer = nullptr;
std::atomic<bool> m_startupFinished{ false };
#ifdef WITH_RANDOMX
uv_mutex_t m_minerLock;
Miner* m_miner = nullptr;
@@ -205,8 +221,9 @@ private:
std::atomic<uint64_t> m_zmqLastActive;
uint64_t m_startTime;
uv_async_t m_restartZMQAsync;
uv_async_t m_reconnectToHostAsync;
mutable uv_rwlock_t m_ZMQReaderLock;
ZMQReader* m_ZMQReader = nullptr;
hash m_getMinerDataHash;
+8 -2
View File
@@ -24,7 +24,7 @@
#include <sys/stat.h>
#endif
static constexpr char log_category_prefix[] = "P2Pool API ";
LOG_CATEGORY(P2Pool API)
namespace p2pool {
@@ -137,8 +137,14 @@ void p2pool_api::dump_to_file()
data = std::move(m_dumpData);
}
char buf[log::Stream::BUF_SIZE + 1];
buf[0] = '\0';
for (auto& it : data) {
DumpFileWork* work = new DumpFileWork{ {}, 0, it.first, it.first + std::to_string(m_counter), std::move(it.second) };
log::Stream s(buf);
s << it.first << m_counter << '\0';
DumpFileWork* work = new DumpFileWork{ {}, 0, it.first, buf, std::move(it.second) };
work->req.data = work;
++m_counter;
+81 -5
View File
@@ -20,6 +20,8 @@
#include "stratum_server.h"
#include "p2p_server.h"
LOG_CATEGORY(Params)
void p2pool_usage();
namespace p2pool {
@@ -30,17 +32,35 @@ Params::Params(int argc, char* const argv[])
bool ok = false;
if ((strcmp(argv[i], "--host") == 0) && (i + 1 < argc)) {
m_host = argv[++i];
const char* address = argv[++i];
if (m_hosts.empty()) {
m_hosts.emplace_back(Host());
m_hosts.back().m_address = address;
}
else {
const Host& h = m_hosts.back();
m_hosts.emplace_back(address, h.m_rpcPort, h.m_zmqPort, "");
}
ok = true;
}
if ((strcmp(argv[i], "--rpc-port") == 0) && (i + 1 < argc)) {
m_rpcPort = std::min(std::max(strtoul(argv[++i], nullptr, 10), 1UL), 65535UL);
if (m_hosts.empty()) {
m_hosts.emplace_back(Host());
}
m_hosts.back().m_rpcPort = std::min(std::max(strtoul(argv[++i], nullptr, 10), 1UL), 65535UL);
ok = true;
}
if ((strcmp(argv[i], "--zmq-port") == 0) && (i + 1 < argc)) {
m_zmqPort = std::min(std::max(strtoul(argv[++i], nullptr, 10), 1UL), 65535UL);
if (m_hosts.empty()) {
m_hosts.emplace_back(Host());
}
m_hosts.back().m_zmqPort = std::min(std::max(strtoul(argv[++i], nullptr, 10), 1UL), 65535UL);
ok = true;
}
@@ -133,7 +153,11 @@ Params::Params(int argc, char* const argv[])
}
if ((strcmp(argv[i], "--rpc-login") == 0) && (i + 1 < argc)) {
m_rpcLogin = argv[++i];
if (m_hosts.empty()) {
m_hosts.emplace_back(Host());
}
m_hosts.back().m_rpcLogin = argv[++i];
ok = true;
}
@@ -172,6 +196,21 @@ Params::Params(int argc, char* const argv[])
}
}
auto invalid_host = [](const Host& h)
{
if (!h.valid()) {
LOGERR(1, "Invalid host " << h.m_address << ':' << h.m_rpcPort << ":ZMQ:" << h.m_zmqPort << ". Try \"p2pool --help\".");
return true;
}
return false;
};
m_hosts.erase(std::remove_if(m_hosts.begin(), m_hosts.end(), invalid_host), m_hosts.end());
if (m_hosts.empty()) {
m_hosts.emplace_back(Host());
}
if (m_stratumAddresses.empty()) {
const int stratum_port = DEFAULT_STRATUM_PORT;
@@ -185,7 +224,44 @@ Params::Params(int argc, char* const argv[])
bool Params::valid() const
{
return !m_host.empty() && m_rpcPort && m_zmqPort && m_wallet.valid();
if (!m_wallet.valid()) {
LOGERR(1, "Invalid wallet address. Try \"p2pool --help\".");
return false;
}
return true;
}
bool Params::Host::init_display_name(const Params& p)
{
m_displayName = m_address;
if (p.m_socks5Proxy.empty()) {
if (p.m_dns) {
bool is_v6;
if (!resolve_host(m_address, is_v6)) {
LOGERR(1, "resolve_host failed for " << m_address);
return false;
}
}
else if (m_address.find_first_not_of("0123456789.:") != std::string::npos) {
LOGERR(1, "Can't resolve hostname " << m_address << " with DNS disabled");
return false;
}
}
char buf[log::Stream::BUF_SIZE + 1];
buf[0] = '\0';
log::Stream s(buf);
s << m_displayName << ':' << m_rpcPort << ":ZMQ:" << m_zmqPort;
if (m_address != m_displayName) {
s << " (" << m_address << ')';
}
m_displayName.assign(buf, s.m_pos);
return true;
}
} // namespace p2pool
+26 -4
View File
@@ -27,9 +27,32 @@ struct Params
bool valid() const;
std::string m_host = "127.0.0.1";
uint32_t m_rpcPort = 18081;
uint32_t m_zmqPort = 18083;
struct Host
{
Host() : m_address("127.0.0.1"), m_rpcPort(18081), m_zmqPort(18083) {}
Host(const char* address, uint32_t rpcPort, uint32_t zmqPort, const char* rpcLogin)
: m_address(address)
, m_rpcPort(rpcPort)
, m_zmqPort(zmqPort)
, m_rpcLogin(rpcLogin)
{}
bool valid() const { return !m_address.empty() && m_rpcPort && m_zmqPort && (m_rpcPort != m_zmqPort); }
bool init_display_name(const Params& p);
std::string m_address;
uint32_t m_rpcPort;
uint32_t m_zmqPort;
std::string m_rpcLogin;
std::string m_displayName;
};
std::vector<Host> m_hosts;
bool m_lightMode = false;
Wallet m_wallet{ nullptr };
std::string m_stratumAddresses;
@@ -49,7 +72,6 @@ struct Params
uint32_t m_minerThreads = 0;
bool m_mini = false;
bool m_autoDiff = true;
std::string m_rpcLogin;
std::string m_socks5Proxy;
bool m_dns = true;
uint32_t m_p2pExternalPort = 0;
+1 -1
View File
@@ -22,7 +22,7 @@
#include "pow_hash.h"
#include "crypto.h"
static constexpr char log_category_prefix[] = "PoolBlock ";
LOG_CATEGORY(PoolBlock)
#include "pool_block_parser.inl"
+1 -2
View File
@@ -393,8 +393,7 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, const SideChain& si
}
}
catch (std::exception& e) {
const char* msg = e.what();
LOGERR(0, "Exception in PoolBlock::deserialize(): " << (msg ? msg : "unknown exception"));
LOGERR(0, "Exception in PoolBlock::deserialize(): " << e.what());
return __LINE__;
}
+24 -10
View File
@@ -29,7 +29,7 @@
#include <rapidjson/document.h>
#include <thread>
static constexpr char log_category_prefix[] = "RandomX_Hasher ";
LOG_CATEGORY(RandomX_Hasher)
namespace p2pool {
@@ -322,6 +322,22 @@ void RandomX_Hasher::sync_wait()
ReadLock lock2(m_cacheLock);
}
static bool randomx_calculate_hash_safe(randomx_vm* machine, const void* input, size_t inputSize, void* output)
{
// Try to calculate the hash again if something went wrong the first time (for example, because of an unstable CPU)
for (size_t i = 0; i < 2; ++i) {
try {
randomx_calculate_hash(machine, input, inputSize, output);
return true;
}
catch (const std::exception& e) {
LOGERR(0, "Failed to calculate RandomX hash: exception \"" << e.what() << "\". Is your CPU/RAM unstable?" <<
"\nFailed RandomX hash input: " << log::hex_buf(input, inputSize));
}
}
return false;
}
bool RandomX_Hasher::calculate(const void* data, size_t size, uint64_t /*height*/, const hash& seed, hash& result, bool force_light_mode)
{
// First try to use the dataset if it's ready
@@ -335,8 +351,7 @@ bool RandomX_Hasher::calculate(const void* data, size_t size, uint64_t /*height*
MutexLock lock(m_vm[FULL_DATASET_VM].mutex);
if (m_vm[FULL_DATASET_VM].vm && (seed == m_seed[m_index])) {
randomx_calculate_hash(m_vm[FULL_DATASET_VM].vm, data, size, &result);
return true;
return randomx_calculate_hash_safe(m_vm[FULL_DATASET_VM].vm, data, size, &result);
}
}
@@ -350,8 +365,7 @@ bool RandomX_Hasher::calculate(const void* data, size_t size, uint64_t /*height*
{
MutexLock lock2(m_vm[m_index].mutex);
if (m_vm[m_index].vm && (seed == m_seed[m_index])) {
randomx_calculate_hash(m_vm[m_index].vm, data, size, &result);
return true;
return randomx_calculate_hash_safe(m_vm[m_index].vm, data, size, &result);
}
}
@@ -360,8 +374,7 @@ bool RandomX_Hasher::calculate(const void* data, size_t size, uint64_t /*height*
MutexLock lock2(m_vm[prev_index].mutex);
if (m_vm[prev_index].vm && (seed == m_seed[prev_index])) {
randomx_calculate_hash(m_vm[prev_index].vm, data, size, &result);
return true;
return randomx_calculate_hash_safe(m_vm[prev_index].vm, data, size, &result);
}
return false;
@@ -447,9 +460,10 @@ bool RandomX_Hasher_RPC::calculate(const void* data_ptr, size_t size, uint64_t h
volatile bool done = false;
const Params& params = m_pool->params();
const Params::Host& host = m_pool->current_host();
JSONRPCRequest::call(params.m_host, params.m_rpcPort, buf, params.m_rpcLogin, params.m_socks5Proxy,
[&result, &h](const char* data, size_t size)
JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, params.m_socks5Proxy,
[&result, &h](const char* data, size_t size, double)
{
rapidjson::Document doc;
if (doc.Parse(data, size).HasParseError() || !parseValue(doc, "result", h)) {
@@ -459,7 +473,7 @@ bool RandomX_Hasher_RPC::calculate(const void* data_ptr, size_t size, uint64_t h
}
result = 1;
},
[this, &result, &done](const char* data, size_t size)
[this, &result, &done](const char* data, size_t size, double)
{
if (size > 0) {
LOGWARN(3, "RPC calc_pow: server returned error " << log::const_buf(data, size));
+109 -38
View File
@@ -40,7 +40,7 @@
#include <iterator>
#include <numeric>
static constexpr char log_category_prefix[] = "SideChain ";
LOG_CATEGORY(SideChain)
static constexpr uint64_t MIN_DIFFICULTY = 100000;
static constexpr size_t UNCLE_BLOCK_DEPTH = 3;
@@ -67,7 +67,7 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name)
, m_unclePenalty(20)
, m_precalcFinished(false)
#ifdef DEV_TEST_SYNC
, m_synchronizedTime(0)
, m_firstPruneTime(0)
#endif
{
if (s_networkType == NetworkType::Invalid) {
@@ -168,7 +168,8 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name)
// Hide most consensus ID bytes, we only want it on screen to show that we're on the right sidechain
memset(buf + 8, '*', HASH_SIZE * 2 - 16);
m_consensusIdDisplayStr.assign(buf);
m_consensusIdDisplayStr = buf;
LOGINFO(1, "consensus ID = " << log::LightCyan() << m_consensusIdDisplayStr.c_str());
memcpy(m_consensusHash.h, m_consensusId.data(), HASH_SIZE);
@@ -455,7 +456,7 @@ bool SideChain::get_shares(const PoolBlock* tip, std::vector<MinerShare>& shares
hash h;
keccak(tip->m_txkeySecSeed.h, HASH_SIZE, h.h);
uint64_t seed = *reinterpret_cast<uint64_t*>(h.h);
uint64_t seed = *h.u64();
if (seed == 0) seed = 1;
for (uint64_t i = 0, k; i < n - 1; ++i) {
@@ -602,13 +603,21 @@ bool SideChain::add_external_block(PoolBlock& block, std::vector<hash>& missing_
", mainchain height = " << block.m_txinGenHeight
);
bool not_enough_pow = true;
// Calculate the same hash second time to check if it's an unstable hardware that caused this
hash pow_hash2;
if (block.get_pow_hash(m_pool->hasher(), block.m_txinGenHeight, seed, pow_hash2, true) && (pow_hash2 != pow_hash)) {
LOGERR(0, "UNSTABLE HARDWARE DETECTED: Calculated the same hash twice, got different results: " << pow_hash << " != " << pow_hash2 << " (sidechain id = " << block.m_sidechainId << ')');
if (block.m_difficulty.check_pow(pow_hash2)) {
LOGINFO(3, "add_external_block second result has enough PoW for height = " << block.m_sidechainHeight << ", id = " << block.m_sidechainId);
not_enough_pow = false;
}
}
return false;
if (not_enough_pow) {
return false;
}
}
bool block_found = false;
@@ -693,9 +702,6 @@ bool SideChain::add_block(const PoolBlock& block)
m_blocksByHeight[new_block->m_sidechainHeight].push_back(new_block);
// Pre-calculate eph_public_keys during initial sync
launch_precalc(new_block);
update_depths(new_block);
if (new_block->m_verified) {
@@ -734,7 +740,7 @@ void SideChain::watch_mainchain_block(const ChainMain& data, const hash& possibl
m_watchBlockSidechainId = possible_id;
}
bool SideChain::get_block_blob(const hash& id, std::vector<uint8_t>& blob) const
const PoolBlock* SideChain::get_block_blob(const hash& id, std::vector<uint8_t>& blob) const
{
ReadLock lock(m_sidechainLock);
@@ -746,7 +752,7 @@ bool SideChain::get_block_blob(const hash& id, std::vector<uint8_t>& blob) const
// Don't return stale chain tip
if (block && (block->m_txinGenHeight + 2 < m_pool->miner_data().height)) {
return false;
return nullptr;
}
}
else {
@@ -757,14 +763,14 @@ bool SideChain::get_block_blob(const hash& id, std::vector<uint8_t>& blob) const
}
if (!block) {
return false;
return nullptr;
}
blob = block->serialize_mainchain_data();
const std::vector<uint8_t> sidechain_data = block->serialize_sidechain_data();
blob.insert(blob.end(), sidechain_data.begin(), sidechain_data.end());
return true;
return block;
}
bool SideChain::get_outputs_blob(PoolBlock* block, uint64_t total_reward, std::vector<uint8_t>& blob, uv_loop_t* loop) const
@@ -773,11 +779,12 @@ bool SideChain::get_outputs_blob(PoolBlock* block, uint64_t total_reward, std::v
struct Data
{
FORCEINLINE Data() : counter(0) {}
FORCEINLINE Data() : blockMinerWallet(nullptr), counter(0) {}
Data(Data&&) = delete;
Data& operator=(Data&&) = delete;
std::vector<MinerShare> tmpShares;
Wallet blockMinerWallet;
hash txkeySec;
std::atomic<int> counter;
};
@@ -812,6 +819,7 @@ bool SideChain::get_outputs_blob(PoolBlock* block, uint64_t total_reward, std::v
}
data = std::make_shared<Data>();
data->blockMinerWallet = block->m_minerWallet;
data->txkeySec = block->m_txkeySec;
if (!get_shares(block, data->tmpShares) || !split_reward(total_reward, data->tmpShares, tmpRewards) || (tmpRewards.size() != data->tmpShares.size())) {
@@ -825,6 +833,14 @@ bool SideChain::get_outputs_blob(PoolBlock* block, uint64_t total_reward, std::v
// Helper jobs call get_eph_public_key with indices in descending order
// Current thread will process indices in ascending order so when they meet, everything will be cached
if (loop) {
// Avoid accessing block->m_minerWallet from other threads in "parallel_run" below
for (MinerShare& share : data->tmpShares) {
if (share.m_wallet == &block->m_minerWallet) {
share.m_wallet = &data->blockMinerWallet;
break;
}
}
parallel_run(loop, [data]() {
Data* d = data.get();
hash eph_public_key;
@@ -1014,7 +1030,7 @@ void SideChain::print_status(bool obtain_sidechain_lock) const
}
LOGINFO(0, "status" <<
"\nMonero node = " << m_pool->host_str() <<
"\nMonero node = " << m_pool->current_host().m_displayName <<
"\nMain chain height = " << m_pool->block_template().height() <<
"\nMain chain hashrate = " << log::Hashrate(network_hashrate) <<
"\nSide chain ID = " << (is_default() ? "default" : (is_mini() ? "mini" : m_consensusIdDisplayStr.c_str())) <<
@@ -1745,9 +1761,6 @@ void SideChain::update_chain_tip(const PoolBlock* block)
// Also clear cache because it has data from all old blocks now
clear_crypto_cache();
LOGINFO(0, log::LightCyan() << "SYNCHRONIZED");
#ifdef DEV_TEST_SYNC
m_synchronizedTime = seconds_since_epoch();
#endif
}
}
prune_old_blocks();
@@ -1760,7 +1773,7 @@ void SideChain::update_chain_tip(const PoolBlock* block)
" is not a longer chain than " << tip->m_sidechainId <<
", height " << tip->m_sidechainHeight);
}
else if (block->m_sidechainHeight + UNCLE_BLOCK_DEPTH > tip->m_sidechainHeight) {
else if (m_pool && (block->m_sidechainHeight + UNCLE_BLOCK_DEPTH > tip->m_sidechainHeight)) {
LOGINFO(4, "possible uncle block: id = " << log::Gray() << block->m_sidechainId << log::NoColor() <<
", height = " << log::Gray() << block->m_sidechainHeight);
m_pool->update_block_template_async();
@@ -1774,13 +1787,8 @@ void SideChain::update_chain_tip(const PoolBlock* block)
PoolBlock* SideChain::get_parent(const PoolBlock* block) const
{
if (block) {
auto it = m_blocksById.find(block->m_parent);
if (it != m_blocksById.end()) {
return it->second;
}
}
return nullptr;
auto it = m_blocksById.find(block->m_parent);
return (it != m_blocksById.end()) ? it->second : nullptr;
}
bool SideChain::is_longer_chain(const PoolBlock* block, const PoolBlock* candidate, bool& is_alternative) const
@@ -1928,6 +1936,18 @@ bool SideChain::is_longer_chain(const PoolBlock* block, const PoolBlock* candida
void SideChain::update_depths(PoolBlock* block)
{
const uint64_t precalc_depth = m_chainWindowSize + UNCLE_BLOCK_DEPTH - 1;
auto update_depth = [this, precalc_depth](PoolBlock* b, const uint64_t new_depth) {
const uint64_t old_depth = b->m_depth;
if (old_depth < new_depth) {
b->m_depth = new_depth;
if ((old_depth < precalc_depth) && (new_depth >= precalc_depth)) {
launch_precalc(b);
}
}
};
for (size_t i = 1; i <= UNCLE_BLOCK_DEPTH; ++i) {
auto it = m_blocksByHeight.find(block->m_sidechainHeight + i);
if (it == m_blocksByHeight.end()) {
@@ -1940,12 +1960,12 @@ void SideChain::update_depths(PoolBlock* block)
return;
}
else {
block->m_depth = std::max(block->m_depth, child->m_depth + 1);
update_depth(block, child->m_depth + 1);
}
}
if (std::find(child->m_uncles.begin(), child->m_uncles.end(), block->m_sidechainId) != child->m_uncles.end()) {
block->m_depth = std::max(block->m_depth, child->m_depth + i);
update_depth(block, child->m_depth + i);
}
}
}
@@ -1961,6 +1981,36 @@ void SideChain::update_depths(PoolBlock* block)
verify_loop(block);
}
for (size_t i = 1; i <= UNCLE_BLOCK_DEPTH; ++i) {
auto it = m_blocksByHeight.find(block->m_sidechainHeight + i);
if (it == m_blocksByHeight.end()) {
continue;
}
for (PoolBlock* child : it->second) {
const uint64_t old_depth = child->m_depth;
if (child->m_parent == block->m_sidechainId) {
if (i != 1) {
LOGWARN(3, "Block " << block->m_sidechainId << ": m_sidechainHeight is inconsistent with child's m_sidechainHeight.");
return;
}
else if (block->m_depth > 0) {
update_depth(child, block->m_depth - 1);
}
}
if (std::find(child->m_uncles.begin(), child->m_uncles.end(), block->m_sidechainId) != child->m_uncles.end()) {
if (block->m_depth > i) {
update_depth(child, block->m_depth - i);
}
}
if (child->m_depth > old_depth) {
blocks_to_update.push_back(child);
}
}
}
auto it = m_blocksById.find(block->m_parent);
if (it != m_blocksById.end()) {
if (it->second->m_sidechainHeight + 1 != block->m_sidechainHeight) {
@@ -1969,7 +2019,7 @@ void SideChain::update_depths(PoolBlock* block)
}
if (it->second->m_depth < block->m_depth + 1) {
it->second->m_depth = block->m_depth + 1;
update_depth(it->second, block->m_depth + 1);
blocks_to_update.push_back(it->second);
}
}
@@ -1987,7 +2037,7 @@ void SideChain::update_depths(PoolBlock* block)
const uint64_t d = block->m_sidechainHeight - it->second->m_sidechainHeight;
if (it->second->m_depth < block->m_depth + d) {
it->second->m_depth = block->m_depth + d;
update_depth(it->second, block->m_depth + d);
blocks_to_update.push_back(it->second);
}
}
@@ -2056,22 +2106,43 @@ void SideChain::prune_old_blocks()
finish_precalc();
#ifdef DEV_TEST_SYNC
if (m_pool && m_precalcFinished.load() && (cur_time >= m_synchronizedTime + 120)) {
if (m_firstPruneTime == 0) {
m_firstPruneTime = seconds_since_epoch();
// Test Monero node switching
m_pool->reconnect_to_host();
}
if ((cur_time >= m_firstPruneTime + 120) && !m_pool->stopped()) {
LOGINFO(0, log::LightGreen() << "[DEV] Synchronization finished successfully, stopping P2Pool now");
#ifdef DEV_TRACK_MEMORY
show_top_10_allocations();
#endif
print_status(false);
P2PServer* server = m_pool->p2p_server();
if (server) {
server->print_status();
server->print_bans();
server->show_peers_async();
StratumServer* server1 = m_pool->stratum_server();
P2PServer* server2 = m_pool->p2p_server();
if (server1 && server2) {
server1->print_status();
server2->print_status();
server1->print_bans();
server2->print_bans();
server1->show_workers_async();
server2->show_peers_async();
}
m_pool->print_hosts();
bkg_jobs_tracker.print_status();
m_pool->stop();
}
#endif
}
}
void SideChain::get_missing_blocks(std::vector<hash>& missing_blocks) const
void SideChain::get_missing_blocks(unordered_set<hash>& missing_blocks) const
{
missing_blocks.clear();
@@ -2083,14 +2154,14 @@ void SideChain::get_missing_blocks(std::vector<hash>& missing_blocks) const
}
if (!b.second->m_parent.empty() && (m_blocksById.find(b.second->m_parent) == m_blocksById.end())) {
missing_blocks.push_back(b.second->m_parent);
missing_blocks.insert(b.second->m_parent);
}
int num_missing_uncles = 0;
for (const hash& h : b.second->m_uncles) {
if (!h.empty() && (m_blocksById.find(h) == m_blocksById.end())) {
missing_blocks.push_back(h);
missing_blocks.insert(h);
// Get no more than 2 first missing uncles at a time from each block
// Blocks with more than 2 uncles are very rare and they will be processed in several steps
+4 -3
View File
@@ -52,12 +52,12 @@ public:
bool add_external_block(PoolBlock& block, std::vector<hash>& missing_blocks);
bool add_block(const PoolBlock& block);
void get_missing_blocks(std::vector<hash>& missing_blocks) const;
void get_missing_blocks(unordered_set<hash>& missing_blocks) const;
PoolBlock* find_block(const hash& id) const;
void watch_mainchain_block(const ChainMain& data, const hash& possible_id);
bool get_block_blob(const hash& id, std::vector<uint8_t>& blob) const;
const PoolBlock* get_block_blob(const hash& id, std::vector<uint8_t>& blob) const;
bool get_outputs_blob(PoolBlock* block, uint64_t total_reward, std::vector<uint8_t>& blob, uv_loop_t* loop) const;
void print_status(bool obtain_sidechain_lock = true) const;
@@ -84,6 +84,7 @@ public:
#ifdef P2POOL_UNIT_TESTS
difficulty_type m_testMainChainDiff;
const unordered_map<hash, PoolBlock*>& blocksById() const { return m_blocksById; }
#endif
static bool split_reward(uint64_t reward, const std::vector<MinerShare>& shares, std::vector<uint64_t>& rewards);
@@ -156,7 +157,7 @@ private:
std::atomic<bool> m_precalcFinished;
#ifdef DEV_TEST_SYNC
uint64_t m_synchronizedTime;
uint64_t m_firstPruneTime;
#endif
hash m_consensusHash;
+15 -10
View File
@@ -23,7 +23,7 @@
#include "params.h"
#include "p2pool_api.h"
static constexpr char log_category_prefix[] = "StratumServer ";
LOG_CATEGORY(StratumServer)
static constexpr int DEFAULT_BACKLOG = 128;
static constexpr uint64_t DEFAULT_BAN_TIME = 600;
@@ -293,7 +293,7 @@ bool StratumServer::on_login(StratumClient* client, uint32_t id, const char* log
client->m_rpcId = static_cast<StratumServer*>(client->m_owner)->get_random32();
} while (!client->m_rpcId);
log::hex_buf target_hex(reinterpret_cast<const uint8_t*>(&target), sizeof(uint64_t));
log::hex_buf target_hex(&target);
if (target >= TARGET_4_BYTES_LIMIT) {
target_hex.m_data += sizeof(uint32_t);
@@ -544,6 +544,11 @@ void StratumServer::reset_share_counters()
m_totalFailedShares = 0;
}
const char* StratumServer::get_log_category() const
{
return log_category_prefix;
}
void StratumServer::print_stratum_status() const
{
uint64_t hashes_15m, hashes_1h, hashes_24h, total_hashes;
@@ -589,8 +594,8 @@ void StratumServer::print_stratum_status() const
const uint64_t hashrate_24h = (dt_24h > 0) ? (hashes_24h / dt_24h) : 0;
char shares_failed_buf[64] = {};
log::Stream s(shares_failed_buf);
if (shares_failed) {
log::Stream s(shares_failed_buf);
s << log::Yellow() << "\nShares failed = " << shares_failed << log::NoColor();
}
@@ -775,7 +780,7 @@ void StratumServer::on_blobs_ready()
const bool result = send(client,
[data, target, hashing_blob, job_id](uint8_t* buf, size_t buf_size)
{
log::hex_buf target_hex(reinterpret_cast<const uint8_t*>(&target), sizeof(uint64_t));
log::hex_buf target_hex(&target);
if (target >= TARGET_4_BYTES_LIMIT) {
target_hex.m_data += sizeof(uint32_t);
@@ -930,7 +935,7 @@ void StratumServer::on_share_found(uv_work_t* req)
}
// Send the response to miner
const uint64_t value = *reinterpret_cast<uint64_t*>(share->m_resultHash.h + HASH_SIZE - sizeof(uint64_t));
const uint64_t value = share->m_resultHash.u64()[HASH_SIZE / sizeof(uint64_t) - 1];
if (LIKELY(value < target)) {
const uint64_t timestamp = share->m_timestamp;
@@ -968,19 +973,19 @@ void StratumServer::on_after_share_found(uv_work_t* req, int /*status*/)
const size_t k = static_cast<size_t>(share->m_result);
const char* reason = (k < array_size(reason_list)) ? reason_list[k] : "unknown";
LOGWARN(0, log::Green() << "INVALID SHARE: mainchain height " << share->m_mainchainHeight << ", sidechain height " << share->m_sidechainHeight << ", diff " << share->m_sidechainDifficulty << ", client " << static_cast<char*>(client->m_addrString) << (*s ? ", user " : "") << s << ", reason: " << reason);
LOGWARN(0, "INVALID SHARE: mainchain height " << share->m_mainchainHeight << ", sidechain height " << share->m_sidechainHeight << ", diff " << share->m_sidechainDifficulty << ", client " << static_cast<char*>(client->m_addrString) << (*s ? ", user " : "") << s << ", reason: " << reason);
}
BACKGROUND_JOB_STOP(StratumServer::on_share_found);
}
ON_SCOPE_LEAVE([share]()
StratumServer* server = share->m_server;
ON_SCOPE_LEAVE([share, server]()
{
ASAN_POISON_MEMORY_REGION(share, sizeof(SubmittedShare));
share->m_server->m_submittedSharesPool.push_back(share);
server->m_submittedSharesPool.push_back(share);
});
StratumServer* server = share->m_server;
const bool bad_share = (share->m_result == SubmittedShare::Result::LOW_DIFF) || (share->m_result == SubmittedShare::Result::INVALID_POW);
if ((client->m_resetCounter.load() == share->m_clientResetCounter) && (client->m_rpcId == share->m_rpcId)) {
+1 -1
View File
@@ -97,7 +97,7 @@ public:
void reset_share_counters();
private:
const char* get_category() const override { return "StratumServer "; }
const char* get_log_category() const override;
void print_stratum_status() const;
void update_auto_diff(StratumClient* client, const uint64_t timestamp, const uint64_t hashes);
+12 -5
View File
@@ -27,7 +27,7 @@ TCPServer::TCPServer(int default_backlog, allocate_client_callback allocate_new_
: m_allocateNewClient(allocate_new_client)
, m_defaultBacklog(default_backlog)
, m_loopThread{}
, m_loopThreadRunning(false)
, m_loopThreadCreated(false)
#ifdef WITH_UPNP
, m_portMapping(0)
#endif
@@ -251,6 +251,8 @@ void TCPServer::start_listening(const std::string& listen_addresses, bool upnp)
LOGERR(1, "failed to start event loop thread, error " << uv_err_name(err));
PANIC_STOP();
}
m_loopThreadCreated = true;
}
bool TCPServer::connect_to_peer(bool is_v6, const char* ip, int port)
@@ -474,7 +476,7 @@ void TCPServer::shutdown_tcp()
}
#endif
if (m_loopThreadRunning.load()) {
if (m_loopThreadCreated) {
uv_thread_join(&m_loopThread);
}
@@ -573,13 +575,16 @@ bool TCPServer::send_internal(Client* client, Callback<size_t, uint8_t*, size_t>
return true;
}
const char* TCPServer::get_log_category() const
{
return log_category_prefix;
}
void TCPServer::loop(void* data)
{
TCPServer* server = static_cast<TCPServer*>(data);
server->m_loopThreadRunning.exchange(true);
ON_SCOPE_LEAVE([server]() { server->m_loopThreadRunning.exchange(false); });
log_category_prefix = server->get_category();
log_category_prefix = server->get_log_category();
LOGINFO(1, "event loop started");
server_event_loop_thread = data;
@@ -593,6 +598,7 @@ void TCPServer::loop(void* data)
ASAN_POISON_MEMORY_REGION(wb, sizeof(WriteBuf));
ASAN_POISON_MEMORY_REGION(c, c->size());
ASAN_UNPOISON_MEMORY_REGION(&c->m_resetCounter, sizeof(c->m_resetCounter));
server->m_writeBuffers.emplace(capacity, wb);
server->m_preallocatedClients.emplace_back(c);
@@ -957,6 +963,7 @@ TCPServer::Client* TCPServer::get_client()
void TCPServer::return_client(Client* c)
{
ASAN_POISON_MEMORY_REGION(c, c->size());
ASAN_UNPOISON_MEMORY_REGION(&c->m_resetCounter, sizeof(c->m_resetCounter));
m_preallocatedClients.push_back(c);
}
+2 -2
View File
@@ -143,13 +143,13 @@ private:
std::vector<uv_tcp_t*> m_listenSockets;
protected:
virtual const char* get_category() const { return "TCPServer "; }
virtual const char* get_log_category() const;
std::vector<uint8_t> m_callbackBuf;
int m_defaultBacklog;
uv_thread_t m_loopThread;
std::atomic<bool> m_loopThreadRunning;
std::atomic<bool> m_loopThreadCreated;
static void loop(void* data);
+21 -10
View File
@@ -40,11 +40,17 @@
#include <resolv.h>
#endif
static constexpr char log_category_prefix[] = "Util ";
LOG_CATEGORY(Util)
namespace p2pool {
const char* VERSION = "v" STR2(P2POOL_VERSION_MAJOR) "." STR2(P2POOL_VERSION_MINOR) " (built"
#if defined(P2POOL_VERSION_PATCH) && (P2POOL_VERSION_PATCH > 0)
#define P2POOL_VERSION_PATCH_STR "." STR2(P2POOL_VERSION_PATCH)
#else
#define P2POOL_VERSION_PATCH_STR ""
#endif
const char* VERSION = "v" STR2(P2POOL_VERSION_MAJOR) "." STR2(P2POOL_VERSION_MINOR) P2POOL_VERSION_PATCH_STR " (built"
#if defined(__clang__)
" with clang/" __clang_version__
#elif defined(__GNUC__)
@@ -141,7 +147,7 @@ NOINLINE difficulty_type& difficulty_type::operator/=(difficulty_type b)
NOINLINE bool difficulty_type::check_pow(const hash& pow_hash) const
{
const uint64_t* a = reinterpret_cast<const uint64_t*>(pow_hash.h);
const uint64_t* a = pow_hash.u64();
uint64_t result[6] = {};
uint64_t product[6] = {};
@@ -726,23 +732,26 @@ int add_portmapping(int external_port, int internal_port)
LOGINFO(1, "UPnP: WAN IP address " << log::Gray() << static_cast<const char*>(ext_addr));
}
const std::string eport = std::to_string(external_port);
const std::string iport = std::to_string(internal_port);
char eport[16] = {};
do { log::Stream s(eport); s << external_port; } while (0);
result = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, eport.c_str(), iport.c_str(), local_addr, "P2Pool", "TCP", nullptr, nullptr);
char iport[16] = {};
do { log::Stream s(iport); s << internal_port; } while (0);
result = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, eport, iport, local_addr, "P2Pool", "TCP", nullptr, nullptr);
// ConflictInMappingEntry: try to delete the old record and then add the new one again
if (result == 718) {
LOGWARN(1, "UPNP_AddPortMapping failed: ConflictInMappingEntry");
result = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, eport.c_str(), "TCP", nullptr);
result = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, eport, "TCP", nullptr);
if (result) {
LOGWARN(1, "UPNP_DeletePortMapping returned error " << result);
return 0;
}
else {
LOGINFO(1, "UPnP: Deleted mapping for external port " << external_port);
result = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, eport.c_str(), iport.c_str(), local_addr, "P2Pool", "TCP", nullptr, nullptr);
result = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, eport, iport, local_addr, "P2Pool", "TCP", nullptr, nullptr);
}
}
@@ -776,8 +785,10 @@ void remove_portmapping(int external_port)
return;
}
const std::string eport = std::to_string(external_port);
result = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, eport.c_str(), "TCP", nullptr);
char eport[16] = {};
do { log::Stream s(eport); s << external_port; } while (0);
result = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, eport, "TCP", nullptr);
if (result) {
LOGWARN(1, "UPNP_DeletePortMapping returned error " << result);
}
+8 -2
View File
@@ -35,7 +35,8 @@
namespace p2pool {
#define P2POOL_VERSION_MAJOR 3
#define P2POOL_VERSION_MINOR 4
#define P2POOL_VERSION_MINOR 6
#define P2POOL_VERSION_PATCH 2
extern const char* VERSION;
@@ -301,12 +302,17 @@ bool get_dns_txt_records_base(const std::string& host, Callback<void, const char
template<typename T>
FORCEINLINE bool get_dns_txt_records(const std::string& host, T&& callback) { return get_dns_txt_records_base(host, Callback<void, const char*, size_t>::Derived<T>(std::move(callback))); }
#ifdef DEV_TRACK_MEMORY
void show_top_10_allocations();
#endif
} // namespace p2pool
void memory_tracking_start();
void memory_tracking_stop();
bool memory_tracking_stop();
void p2pool_usage();
void p2pool_version();
int p2pool_test();
namespace robin_hood {
+87 -34
View File
@@ -20,12 +20,12 @@
#include "json_parsers.h"
#include <rapidjson/document.h>
static constexpr char log_category_prefix[] = "ZMQReader ";
LOG_CATEGORY(ZMQReader)
namespace p2pool {
ZMQReader::ZMQReader(const std::string& address, uint32_t zmq_port, const std::string& proxy, MinerCallbackHandler* handler)
: m_address(address)
: m_monitor(nullptr)
, m_zmqPort(zmq_port)
, m_proxy(proxy)
, m_handler(handler)
@@ -38,12 +38,15 @@ ZMQReader::ZMQReader(const std::string& address, uint32_t zmq_port, const std::s
m_proxy.clear();
}
char addr_buf[log::Stream::BUF_SIZE + 1];
addr_buf[0] = '\0';
std::random_device rd;
for (uint32_t port = 49152 + (rd() % 16384), i = 0; i < 100; ++i, port = (port < 65535) ? (port + 1) : 49152) {
try {
char addr[32];
snprintf(addr, sizeof(addr), "tcp://127.0.0.1:%u", port);
m_publisher.bind(addr);
log::Stream s(addr_buf);
s << "tcp://127.0.0.1:" << port << '\0';
m_publisher.bind(addr_buf);
m_publisherPort = static_cast<uint16_t>(port);
break;
}
@@ -61,29 +64,33 @@ ZMQReader::ZMQReader(const std::string& address, uint32_t zmq_port, const std::s
m_subscriber.set(zmq::sockopt::connect_timeout, 1000);
std::string addr(addr_buf);
if (!connect(addr, false)) {
throw zmq::error_t(EFSM);
}
if (!m_proxy.empty()) {
m_subscriber.set(zmq::sockopt::socks_proxy, zmq::const_buffer(m_proxy.c_str(), m_proxy.length()));
}
std::string addr = "tcp://" + m_address + ':' + std::to_string(m_zmqPort);
if (!connect(addr)) {
log::Stream s(addr_buf);
s << "tcp://" << address << ':' << m_zmqPort << '\0';
addr.assign(addr_buf);
if (!connect(addr, true)) {
throw zmq::error_t(EFSM);
}
m_address = std::move(addr);
m_subscriber.set(zmq::sockopt::socks_proxy, zmq::const_buffer());
addr = "tcp://127.0.0.1:" + std::to_string(m_publisherPort);
if (!connect(addr)) {
throw zmq::error_t(EFSM);
}
m_subscriber.set(zmq::sockopt::subscribe, "json-full-chain_main");
m_subscriber.set(zmq::sockopt::subscribe, "json-full-miner_data");
m_subscriber.set(zmq::sockopt::subscribe, "json-minimal-txpool_add");
const int err = uv_thread_create(&m_worker, run_wrapper, this);
if (err) {
LOGERR(1, "failed to start ZMQ thread, error " << uv_err_name(err));
LOGERR(1, "failed to start ZMQ worker thread, error " << uv_err_name(err));
throw zmq::error_t(EMTHREAD);
}
}
@@ -92,18 +99,43 @@ ZMQReader::~ZMQReader()
{
LOGINFO(1, "stopping");
m_finished.exchange(true);
stop();
uv_thread_join(&m_worker);
delete m_monitor;
LOGINFO(1, "stopped");
}
void ZMQReader::stop()
{
if (m_stopped.exchange(true)) {
return;
}
try {
const char msg[] = "json-minimal-txpool_add:[]";
m_publisher.send(zmq::const_buffer(msg, sizeof(msg) - 1));
uv_thread_join(&m_worker);
static constexpr char dummy_msg[] = "json-minimal-txpool_add:[]";
m_publisher.send(zmq::const_buffer(dummy_msg, sizeof(dummy_msg) - 1));
}
catch (const std::exception& e) {
LOGERR(1, "exception " << e.what());
}
}
void ZMQReader::monitor_thread(void* arg)
{
LOGINFO(1, "monitor thread ready");
ZMQReader* r = reinterpret_cast<ZMQReader*>(arg);
do {} while (!r->m_stopped && r->m_monitor->m_connected && r->m_monitor->check_event(-1));
// If not connected anymore, shut down ZMQReader entirely
r->stop();
LOGINFO(1, "monitor thread stopped");
}
void ZMQReader::run_wrapper(void* arg)
{
reinterpret_cast<ZMQReader*>(arg)->run();
@@ -112,8 +144,8 @@ void ZMQReader::run_wrapper(void* arg)
void ZMQReader::run()
{
m_threadRunning = true;
ON_SCOPE_LEAVE([this]() { m_threadRunning = false; });
m_workerThreadRunning = true;
ON_SCOPE_LEAVE([this]() { m_workerThreadRunning = false; });
zmq_msg_t message = {};
@@ -123,6 +155,17 @@ void ZMQReader::run()
throw zmq::error_t(errno);
}
const int err = uv_thread_create(&m_monitorThread, monitor_thread, this);
if (err) {
LOGERR(1, "failed to start ZMQ monitor thread, error " << uv_err_name(err));
throw zmq::error_t(EMTHREAD);
}
ON_SCOPE_LEAVE([this]() {
m_monitor->abort();
uv_thread_join(&m_monitorThread);
});
LOGINFO(1, "worker thread ready");
do {
@@ -131,7 +174,7 @@ void ZMQReader::run()
throw zmq::error_t(errno);
}
if (m_finished.load()) {
if (m_stopped) {
break;
}
@@ -145,19 +188,20 @@ void ZMQReader::run()
zmq_msg_close(&message);
}
bool ZMQReader::connect(const std::string& address)
void ZMQReader::Monitor::on_event_connected(const zmq_event_t&, const char* address)
{
struct ConnectMonitor : public zmq::monitor_t
{
void on_event_connected(const zmq_event_t&, const char* address) ZMQ_OVERRIDE
{
LOGINFO(1, "connected to " << address);
connected = true;
}
LOGINFO(1, "connected to " << address);
m_connected = true;
}
bool connected = false;
} monitor;
void ZMQReader::Monitor::on_event_disconnected(const zmq_event_t&, const char* address)
{
LOGERR(1, "disconnected from " << address);
m_connected = false;
}
bool ZMQReader::connect(const std::string& address, bool keep_monitor)
{
static uint64_t id = 0;
if (!id) {
@@ -165,7 +209,7 @@ bool ZMQReader::connect(const std::string& address)
id = (static_cast<uint64_t>(rd()) << 32) | static_cast<uint32_t>(rd());
}
char buf[log::Stream::BUF_SIZE + 1];
char buf[64];
log::Stream s(buf);
s << "inproc://p2pool-connect-mon-" << id << '\0';
++id;
@@ -173,16 +217,25 @@ bool ZMQReader::connect(const std::string& address)
using namespace std::chrono;
const auto start_time = steady_clock::now();
monitor.init(m_subscriber, buf);
Monitor* monitor = new Monitor();
monitor->init(m_subscriber, buf);
m_subscriber.connect(address);
while (!monitor.connected && monitor.check_event(-1)) {
while (!monitor->m_connected && monitor->check_event(-1)) {
if (duration_cast<milliseconds>(steady_clock::now() - start_time).count() >= 1000) {
LOGERR(1, "failed to connect to " << address);
delete monitor;
return false;
}
}
if (keep_monitor) {
m_monitor = monitor;
}
else {
delete monitor;
}
return true;
}
@@ -206,7 +259,7 @@ void ZMQReader::parse(char* data, size_t size)
using namespace rapidjson;
Document doc;
if (doc.Parse<kParseCommentsFlag | kParseTrailingCommasFlag>(value, end - value).HasParseError()) {
if (doc.Parse(value, end - value).HasParseError()) {
LOGWARN(1, "ZeroMQ message failed to parse, skipping it");
return;
}
+21 -4
View File
@@ -27,12 +27,29 @@ public:
ZMQReader(const std::string& address, uint32_t zmq_port, const std::string& proxy, MinerCallbackHandler* handler);
~ZMQReader();
bool is_running() const { return m_threadRunning.load(); }
bool is_running() const { return m_workerThreadRunning.load(); }
private:
struct Monitor : public zmq::monitor_t {
Monitor() : m_connected(false) {}
Monitor(const Monitor&) = delete;
void on_event_connected(const zmq_event_t&, const char* address) ZMQ_OVERRIDE;
void on_event_disconnected(const zmq_event_t&, const char* address) ZMQ_OVERRIDE;
std::atomic<bool> m_connected;
} *m_monitor;
static void monitor_thread(void* arg);
uv_thread_t m_monitorThread{};
private:
void stop();
static void run_wrapper(void* arg);
void run();
bool connect(const std::string& address);
bool connect(const std::string& address, bool keep_monitor);
void parse(char* data, size_t size);
@@ -46,8 +63,8 @@ private:
zmq::socket_t m_publisher{ m_context, ZMQ_PUB };
zmq::socket_t m_subscriber{ m_context, ZMQ_SUB };
uint16_t m_publisherPort = 0;
std::atomic<bool> m_finished{ false };
std::atomic<bool> m_threadRunning{ false };
std::atomic<bool> m_stopped{ false };
std::atomic<bool> m_workerThreadRunning{ false };
TxMempoolData m_tx;
MinerData m_minerData;
+4 -2
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.12)
cmake_minimum_required(VERSION 3.5)
project(p2pool_tests)
option(STATIC_LIBS "Use locally built libuv and libzmq static libs" OFF)
@@ -96,7 +96,7 @@ include_directories(googletest/googletest/include)
if (WIN32)
set(LIBS ${LIBS} ws2_32 iphlpapi userenv psapi dnsapi dbghelp)
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
if ((CMAKE_CXX_COMPILER_ID MATCHES GNU) OR (CMAKE_CXX_COMPILER_ID MATCHES Clang))
set(LIBS ${LIBS} bcrypt)
endif()
add_definitions(-DCURL_STATICLIB)
@@ -174,6 +174,8 @@ if (HAVE_BITSCANREVERSE64)
add_definitions(/DHAVE_BITSCANREVERSE64)
endif()
add_definitions("-DRAPIDJSON_PARSE_DEFAULT_FLAGS=kParseTrailingCommasFlag")
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES})
target_link_libraries(${CMAKE_PROJECT_NAME} debug ${ZMQ_LIBRARY_DEBUG} debug ${UV_LIBRARY_DEBUG} debug ${CURL_LIBRARY_DEBUG} optimized ${ZMQ_LIBRARY} optimized ${UV_LIBRARY} optimized ${CURL_LIBRARY} ${LIBS})
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/src/crypto_tests.txt" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
+7 -2
View File
@@ -27,7 +27,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
endif()
elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
set(GENERAL_FLAGS "")
set(WARNING_FLAGS "/Wall /sdl")
set(WARNING_FLAGS "/W4 /sdl")
set(SECURITY_FLAGS "/GS /guard:cf")
set(OPTIMIZATION_FLAGS "/O2 /Oi /Ob2 /Ot /DNDEBUG /GL")
@@ -41,7 +41,12 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${GENERAL_FLAGS} ${WARNING_FLAGS} ${SECURITY_FLAGS} /Ob1 /Ot /Zi /MT")
elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
set(GENERAL_FLAGS "-pthread")
if (WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
else()
set(GENERAL_FLAGS "-pthread")
endif()
set(WARNING_FLAGS "-Wall -Wextra -Wno-undefined-internal")
set(OPTIMIZATION_FLAGS "-Ofast -funroll-loops -fmerge-all-constants -flto")
+4 -4
View File
@@ -74,8 +74,8 @@ TEST(block_template, update)
ASSERT_EQ(diff, 300346053753ULL);
ASSERT_EQ(sidechain_diff, sidechain.difficulty());
ASSERT_EQ(seed_hash, data.seed_hash);
ASSERT_EQ(nonce_offset, 39);
ASSERT_EQ(template_id, 1);
ASSERT_EQ(nonce_offset, 39U);
ASSERT_EQ(template_id, 1U);
hash blobs_hash;
keccak(blobs.data(), static_cast<int>(blobs.size()), blobs_hash.h);
@@ -105,8 +105,8 @@ TEST(block_template, update)
ASSERT_EQ(diff, 300346053753ULL);
ASSERT_EQ(sidechain_diff, sidechain.difficulty());
ASSERT_EQ(seed_hash, data.seed_hash);
ASSERT_EQ(nonce_offset, 39);
ASSERT_EQ(template_id, 2);
ASSERT_EQ(nonce_offset, 39U);
ASSERT_EQ(template_id, 2U);
keccak(blobs.data(), static_cast<int>(blobs.size()), blobs_hash.h);
ASSERT_EQ(blobs_hash, H("c74d295a9cb7e808030284e2169a6f05b685a11c6c577a774d5eb8fad175d5cd"));
+2 -2
View File
@@ -567,8 +567,8 @@ TEST(difficulty_type, check_pow)
for (int i = 0; i < 1000; ++i) {
// Random difficulty between 300G and 400G
difficulty_type diff{ 300000000000ull + (r() % 100000000000ull), 0 };
hash h;
diff.lo = 300000000000ull + (r() % 100000000000ull);
diff.hi = 0;
// All zeros
memset(h.h, 0, HASH_SIZE);
Binary file not shown.
+2
View File
@@ -18,9 +18,11 @@
#include "gtest/gtest.h"
void p2pool_usage() {}
namespace p2pool { void set_main_thread(); }
int main(int argc, char** argv)
{
p2pool::set_main_thread();
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
+60 -25
View File
@@ -57,33 +57,41 @@ TEST(pool_block, deserialize)
int outputs_offset, outputs_blob_size;
const std::vector<uint8_t> mainchain_data = b.serialize_mainchain_data(&header_size, &miner_tx_size, &outputs_offset, &outputs_blob_size);
ASSERT_EQ(mainchain_data.size(), 1757);
ASSERT_EQ(header_size, 43);
ASSERT_EQ(miner_tx_size, 1457);
ASSERT_EQ(mainchain_data.size(), 1757U);
ASSERT_EQ(header_size, 43U);
ASSERT_EQ(miner_tx_size, 1457U);
ASSERT_EQ(outputs_offset, 54);
ASSERT_EQ(outputs_blob_size, 1371);
ASSERT_EQ(b.m_majorVersion, 16);
ASSERT_EQ(b.m_minorVersion, 16);
ASSERT_EQ(b.m_timestamp, 1679221824);
ASSERT_EQ(b.m_nonce, 1247);
ASSERT_EQ(b.m_txinGenHeight, 2845298);
ASSERT_EQ(b.m_outputs.size(), 35);
ASSERT_EQ(b.m_extraNonceSize, 4);
ASSERT_EQ(b.m_extraNonce, 1482827308);
ASSERT_EQ(b.m_transactions.size(), 9);
ASSERT_EQ(b.m_uncles.size(), 0);
ASSERT_EQ(b.m_sidechainHeight, 4674483);
ASSERT_EQ(b.m_difficulty.lo, 1854596983);
ASSERT_EQ(b.m_difficulty.hi, 0);
ASSERT_EQ(b.m_majorVersion, 16U);
ASSERT_EQ(b.m_minorVersion, 16U);
ASSERT_EQ(b.m_timestamp, 1679221824U);
ASSERT_EQ(b.m_nonce, 1247U);
ASSERT_EQ(b.m_txinGenHeight, 2845298U);
ASSERT_EQ(b.m_outputs.size(), 35U);
ASSERT_EQ(b.m_extraNonceSize, 4U);
ASSERT_EQ(b.m_extraNonce, 1482827308U);
ASSERT_EQ(b.m_transactions.size(), 9U);
ASSERT_EQ(b.m_uncles.size(), 0U);
ASSERT_EQ(b.m_sidechainHeight, 4674483U);
ASSERT_EQ(b.m_difficulty.lo, 1854596983U);
ASSERT_EQ(b.m_difficulty.hi, 0U);
ASSERT_EQ(b.m_cumulativeDifficulty.lo, 7172845253120126ull);
ASSERT_EQ(b.m_cumulativeDifficulty.hi, 0);
ASSERT_EQ(b.m_depth, 0);
ASSERT_EQ(b.m_cumulativeDifficulty.hi, 0U);
ASSERT_EQ(b.m_depth, 0U);
ASSERT_EQ(b.m_verified, false);
ASSERT_EQ(b.m_invalid, false);
ASSERT_EQ(b.m_broadcasted, false);
ASSERT_EQ(b.m_wantBroadcast, false);
hash seed;
{
std::stringstream s;
s << "6fc9c4a55eb513eb31955c084d9342e0082987f9e42da042449b7c9001176d3a";
s >> seed;
}
#if defined(__FreeBSD__) || defined(__OpenBSD__)
class RandomX_Hasher_Test : public RandomX_Hasher_Base
{
public:
@@ -107,8 +115,12 @@ TEST(pool_block, deserialize)
return false;
}
} hasher;
#else
RandomX_Hasher hasher(nullptr);
hasher.set_seed(seed);
#endif
hash seed, pow_hash;
hash pow_hash;
ASSERT_EQ(b.get_pow_hash(&hasher, 0, seed, pow_hash), true);
std::stringstream s;
@@ -130,14 +142,14 @@ TEST(pool_block, verify)
const char* m_fileName;
uint64_t m_txinGenHeight;
uint64_t m_sidechainHeight;
bool m_shuffle;
} tests[2] = {
{ "default", "sidechain_dump.dat", 2870010, 4957203 },
{ "mini", "sidechain_dump_mini.dat", 2870010, 4414446 },
{ "default", "sidechain_dump.dat", 2870010, 4957203, true },
{ "mini", "sidechain_dump_mini.dat", 2870010, 4414446, false },
};
for (const STest& t : tests)
{
PoolBlock b;
SideChain sidechain(nullptr, NetworkType::Mainnet, t.m_poolName);
// Difficulty of block 2869248
@@ -151,17 +163,40 @@ TEST(pool_block, verify)
f.read(reinterpret_cast<char*>(buf.data()), buf.size());
ASSERT_EQ(f.good(), true);
std::vector<PoolBlock*> blocks;
for (const uint8_t *p = buf.data(), *e = buf.data() + buf.size(); p < e;) {
ASSERT_TRUE(p + sizeof(uint32_t) <= e);
const uint32_t n = *reinterpret_cast<const uint32_t*>(p);
p += sizeof(uint32_t);
ASSERT_TRUE(p + n <= e);
ASSERT_EQ(b.deserialize(p, n, sidechain, nullptr, false), 0);
PoolBlock* b = new PoolBlock();
ASSERT_EQ(b->deserialize(p, n, sidechain, nullptr, false), 0);
p += n;
ASSERT_TRUE(sidechain.add_block(b));
ASSERT_TRUE(sidechain.find_block(b.m_sidechainId) != nullptr);
blocks.push_back(b);
}
if (t.m_shuffle) {
std::mt19937_64 rng;
for (uint64_t i = 0, k, n = blocks.size(); i < n - 1; ++i) {
umul128(rng(), n - i, &k);
std::swap(blocks[i], blocks[i + k]);
}
}
for (uint64_t i = 0, n = blocks.size(); i < n; ++i) {
ASSERT_TRUE(sidechain.add_block(*blocks[i]));
ASSERT_TRUE(sidechain.find_block(blocks[i]->m_sidechainId) != nullptr);
delete blocks[i];
}
for (auto it = sidechain.blocksById().begin(); it != sidechain.blocksById().end(); ++it) {
const PoolBlock* b = it->second;
ASSERT_TRUE(b->m_verified);
ASSERT_FALSE(b->m_invalid);
}
const PoolBlock* tip = sidechain.chainTip();
+76 -14
View File
@@ -1,37 +1,99 @@
import socket
import time
import sys
import json
f = open('stratum_dummy' + sys.argv[1] + '.log', 'wb');
f = open('stratum_dummy' + sys.argv[1] + '.log', 'wb')
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(1)
sock.setblocking(True)
f.write(b'Connecting')
f.flush()
time.sleep(5)
while True:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(1)
sock.setblocking(True)
while sock.connect_ex(('127.0.0.1', 3333)) != 0:
f.write(b'.\n')
if sock.connect_ex(('127.0.0.1', 3333)) == 0:
break;
sock.close()
f.write(b'.')
f.flush()
print('.')
time.sleep(1)
diff = '';
f.write(b'\n')
f.flush()
diff = ''
if (sys.argv[1] == '2'):
diff = '+1000';
diff = '+1000'
if (sys.argv[1] == '3'):
diff = '+10000000';
diff = '+10000000'
request = '{"id":1,"method":"login","params":{"login":"x' + diff + '"}}\n'
msg_id = 1
request = '{"id":' + str(msg_id) + ',"method":"login","params":{"login":"x' + diff + '"}}\n'
msg_id += 1
s = '-> ' + request
print(s, end='')
sock.sendall(request.encode('utf-8'))
f.write(s.encode('utf-8'))
f.flush()
rpc_id = ''
while True:
data = sock.recv(1024)
if len(data) == 0:
break;
f.write(data)
break
s = '<- ' + data.decode('utf-8')
print(s, end='')
f.write(s.encode('utf-8'))
f.flush()
print(data.decode('utf-8'))
obj = json.loads(data)
job_id = ''
if ('method' in obj) and ('params' in obj) and (obj['method'] == 'job'):
job_id = obj['params']['job_id']
target = obj['params']['target']
elif ('result' in obj) and ('job' in obj['result']):
if ('id' in obj['result']):
rpc_id = obj['result']['id']
job_id = obj['result']['job']['job_id']
target = obj['result']['job']['target']
if (job_id != ''):
if (msg_id < 4):
result = ('f' if (msg_id == 2) else '0') * 64
request = '{"id":' + str(msg_id) + ',"method":"submit","params":{"id":"' + rpc_id + '","job_id":"' + job_id + '","nonce":"ffffffff","result":"' + result + '"}}\n'
elif (msg_id == 4):
request = '{"id":' + str(msg_id) + ',"method":"keepalived"}\n'
else:
t = bytearray.fromhex(target)
for i in range(len(t)):
if (t[i] > 0):
t[i] -= 1
break
else:
t[i] = 255
result = ('f' * (64 - len(target))) + t.hex()
request = '{"id":' + str(msg_id) + ',"method":"submit","params":{"id":"' + rpc_id + '","job_id":"' + job_id + '","nonce":"ffffffff","result":"' + result + '"}}\n'
msg_id += 1
s = '-> ' + request
print(s, end='')
sock.sendall(request.encode('utf-8'))
f.write(s.encode('utf-8'))
f.flush()
sock.close()
f.close()