Compare commits

...

73 Commits

Author SHA1 Message Date
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
SChernykh 143960937e p2pool v3.4
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
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-05-31 18:11:01 +02:00
SChernykh ee16ce10c1 Tweaked block_seen logic 2023-05-31 17:03:45 +02:00
SChernykh 3988a69946 Added MacOS aarch64 build 2023-05-31 10:42:24 +02:00
SChernykh 738b2e416e ZMQ: log internal listening port 2023-05-30 12:58:03 +02:00
SChernykh b96dfa602b ZMQ: use random port for internal use 2023-05-29 14:37:20 +02:00
SChernykh 9d6f232dd1 Tweaked block_seen logic 2023-05-29 14:13:11 +02:00
SChernykh d808ba6cbf Fixed --rpc-login 2023-05-27 10:52:53 +02:00
SChernykh 818fab8909 Build curl with cmake 2023-05-27 09:21:18 +02:00
SChernykh 1ffaf3a292 Recompiled curl lib for MSVC using cmake 2023-05-26 19:25:18 +02:00
SChernykh 8e11c3dffd Updated libuv 2023-05-26 18:52:49 +02:00
SChernykh a7496dbc02 Updated tests 2023-05-26 15:21:40 +02:00
SChernykh 9e439044de Update rapidjson 2023-05-26 13:25:03 +02:00
SChernykh 536552b9db Update RandomX 2023-05-26 12:50:10 +02:00
SChernykh 183bab110e Refactored log writer 2023-05-26 11:19:39 +02:00
SChernykh beea3e2184 Fixed cppcheck error 2023-05-26 07:48:38 +02:00
SChernykh e0a3add5f2 Refactored is_localhost() 2023-05-26 00:02:15 +02:00
SChernykh fd8e5e4eed Create libcxx_msan.yml 2023-05-25 18:42:03 +02:00
SChernykh 6f7139fe28 CI: added address sanitizer to test sync 2023-05-25 13:11:29 +02:00
SChernykh 57d996491e Update test-sync.yml 2023-05-25 12:08:22 +02:00
SChernykh ba8e0578ed Fixed data race 2023-05-25 11:34:42 +02:00
SChernykh 65b267c497 CI: run cppcheck every day 2023-05-25 11:16:22 +02:00
SChernykh 512064de61 CI: run sync test every 3 hours 2023-05-25 10:29:38 +02:00
SChernykh 2cdb8b5323 P2PServer: fixed use after free on shutdown 2023-05-25 10:11:24 +02:00
SChernykh d08ac60fd9 CI: set difficulties for fake stratum clients
Client 1: autodiff
Client 2: fixed 1000 diff
Client 3: fixed 10M diff
2023-05-25 09:44:44 +02:00
SChernykh fbc0159453 Added UB sanitizer 2023-05-25 09:02:47 +02:00
SChernykh 3d526cebbc Enabled MemorySanitizer 2023-05-25 07:32:33 +02:00
SChernykh 2d10a6a270 CI: added test sync with clang's memory sanitizer 2023-05-24 15:13:37 +02:00
SChernykh 5f7ce28682 TCPServer: fixed send callback arguments 2023-05-24 13:46:05 +02:00
SChernykh 9d0f835186 Update includes.txt 2023-05-24 11:12:13 +02:00
SChernykh 3fdadf3eb5 Fixed cppcheck errors 2023-05-23 20:11:00 +02:00
SChernykh cd57ab6ad9 Fixed UV_THREADPOOL_SIZE setting
putenv can't use stack buffer
2023-05-23 19:14:15 +02:00
SChernykh eab8a51bb7 SideChain: tweaked m_seenBlocks cleanup logic 2023-05-22 15:30:57 +02:00
SChernykh dbb4efb98a Added version console command 2023-05-20 15:51:36 +02:00
SChernykh a83d6deec1 Check node ping at startup 2023-05-18 10:33:27 +02:00
SChernykh f212de64f5 P2PServer: fixed peer list request logic 2023-05-18 09:39:04 +02:00
SChernykh 6a4583f758 Sync test: keep running for 2 minutes more 2023-05-18 00:28:49 +02:00
SChernykh 325f2dc22f Sync test: run with TSAN on Ubuntu 2023-05-17 23:06:54 +02:00
SChernykh 7134187dc9 Sync test: added stratum connections 2023-05-17 20:35:51 +02:00
SChernykh b20db0a117 P2PServer: always send peer list request to new peers 2023-05-17 11:13:25 +02:00
SChernykh 3c7fcf65a9 Fixed DNS TXT parsing 2023-05-12 15:41:02 +02:00
SChernykh 4fa344a0f7 Refactored DNS TXT resolver code 2023-05-12 10:37:58 +02:00
SChernykh 9aa748e628 Fixed FreeBSD build 2023-05-11 10:32:37 +02:00
SChernykh bba4f8d0c5 Fixed headers for res_query 2023-05-11 09:21:10 +02:00
SChernykh be8b38e5cf Changed BLOCK_FOUND wording 2023-05-11 08:07:05 +02:00
SChernykh db9e5ba332 P2PServer: prefer DNS TXT records to load seed nodes 2023-05-10 22:07:35 +02:00
SChernykh 689fa14cfd Fixed cppcheck errors 2023-05-10 10:35:23 +02:00
SChernykh fa924171c7 Statistics webserver: added missing Stratum data 2023-05-10 10:02:17 +02:00
SChernykh 8a222d5e75 TCPServer: check if loop thread is running before waiting for it 2023-05-01 20:13:57 +02:00
60 changed files with 1472 additions and 483 deletions
+70 -16
View File
@@ -63,7 +63,7 @@ jobs:
run: |
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt update
sudo apt install -y git build-essential cmake autoconf libgss-dev gcc-12 g++-12
sudo apt install -y git build-essential cmake libgss-dev gcc-12 g++-12
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100 --slave /usr/bin/g++ g++ /usr/bin/g++-12 --slave /usr/bin/gcov gcov /usr/bin/gcov-12
- name: Checkout repository
@@ -74,9 +74,9 @@ jobs:
- name: Build libcurl
run: |
cd external/src/curl
autoreconf -fi
./configure CFLAGS='-Os' --without-ssl --without-hyper --without-zlib --without-brotli --without-zstd --without-default-ssl-backend --without-ca-bundle --without-ca-path --without-ca-fallback --without-libpsl --without-libgsasl --without-librtmp --without-winidn --without-libidn2 --without-nghttp2 --without-ngtcp2 --without-nghttp3 --without-quiche --without-msh3 --without-zsh-functions-dir --without-fish-functions-dir --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb --disable-smtp --disable-gopher --disable-mqtt --disable-manual --disable-ntlm --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --disable-cookies --disable-socketpair --disable-doh --disable-dateparse --disable-netrc --disable-progress-meter --disable-dnsshuffle --disable-hsts --disable-alt-svc --disable-ares
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
make -j$(nproc)
cd lib && mkdir .libs && cp libcurl.a .libs
- name: Build libuv
run: |
@@ -136,7 +136,7 @@ jobs:
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y git build-essential cmake autoconf 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
- name: Checkout repository
uses: actions/checkout@v3
@@ -146,9 +146,9 @@ jobs:
- name: Build libcurl
run: |
cd external/src/curl
autoreconf -fi
./configure --host=aarch64-linux-gnu CFLAGS='-Os' --without-ssl --without-hyper --without-zlib --without-brotli --without-zstd --without-default-ssl-backend --without-ca-bundle --without-ca-path --without-ca-fallback --without-libpsl --without-libgsasl --without-librtmp --without-winidn --without-libidn2 --without-nghttp2 --without-ngtcp2 --without-nghttp3 --without-quiche --without-msh3 --without-zsh-functions-dir --without-fish-functions-dir --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb --disable-smtp --disable-gopher --disable-mqtt --disable-manual --disable-ntlm --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --disable-cookies --disable-socketpair --disable-doh --disable-dateparse --disable-netrc --disable-progress-meter --disable-dnsshuffle --disable-hsts --disable-alt-svc --disable-ares
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
make -j$(nproc)
cd lib && mkdir .libs && cp libcurl.a .libs
- name: Build libuv
run: |
@@ -198,14 +198,14 @@ jobs:
uses: eine/setup-msys2@v2
with:
update: true
install: mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake make autoconf libtool automake
install: mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake make
- name: Build libcurl
run: |
cd external/src/curl
autoreconf -fi
./configure CFLAGS='-Os' --without-ssl --without-hyper --without-zlib --without-brotli --without-zstd --without-default-ssl-backend --without-ca-bundle --without-ca-path --without-ca-fallback --without-libpsl --without-libgsasl --without-librtmp --without-winidn --without-libidn2 --without-nghttp2 --without-ngtcp2 --without-nghttp3 --without-quiche --without-msh3 --without-zsh-functions-dir --without-fish-functions-dir --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb --disable-smtp --disable-gopher --disable-mqtt --disable-manual --disable-ntlm --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --disable-cookies --disable-socketpair --disable-doh --disable-dateparse --disable-netrc --disable-progress-meter --disable-dnsshuffle --disable-hsts --disable-alt-svc --disable-ares
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
make -j$(nproc)
cd lib && mkdir .libs && cp libcurl.a .libs
- name: Build libuv
run: |
@@ -314,14 +314,14 @@ jobs:
submodules: recursive
- name: Install dependencies
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake autoconf libtool automake
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake
- name: Build libcurl
run: |
cd external/src/curl
autoreconf -fi
./configure CFLAGS='-Os' --without-ssl --without-hyper --without-zlib --without-brotli --without-zstd --without-default-ssl-backend --without-ca-bundle --without-ca-path --without-ca-fallback --without-libpsl --without-libgsasl --without-librtmp --without-winidn --without-libidn2 --without-nghttp2 --without-ngtcp2 --without-nghttp3 --without-quiche --without-msh3 --without-zsh-functions-dir --without-fish-functions-dir --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb --disable-smtp --disable-gopher --disable-mqtt --disable-manual --disable-ntlm --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --disable-cookies --disable-socketpair --disable-doh --disable-dateparse --disable-netrc --disable-progress-meter --disable-dnsshuffle --disable-hsts --disable-alt-svc --disable-ares
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
make -j3
cd lib && mkdir .libs && cp libcurl.a .libs
- name: Build libuv
run: |
@@ -366,6 +366,60 @@ jobs:
name: p2pool-${{ matrix.os }}
path: build/p2pool
build-macos-aarch64:
timeout-minutes: 15
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-11, macos-12]
steps:
- name: Checkout repository
uses: actions/checkout@v3
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
make -j3
cd lib && mkdir .libs && cp libcurl.a .libs
- name: Build libuv
run: |
cd external/src/libuv
mkdir build
cd build
cmake .. -DCMAKE_C_FLAGS='-Os -target arm64-apple-${{ matrix.os }}' -DBUILD_TESTING=OFF
make -j3
- name: Build libzmq
run: |
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
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
make -j3
- name: Archive binary
uses: actions/upload-artifact@v3
with:
name: p2pool-${{ matrix.os }}-aarch64
path: build/p2pool
build-freebsd:
timeout-minutes: 75
@@ -393,12 +447,12 @@ jobs:
version: ${{ matrix.os.version }}
shell: bash
run: |
sudo pkg install -y cmake autoconf automake libtool
sudo pkg install -y cmake
cd external/src/curl
autoreconf -fi
./configure CFLAGS='-Os' --without-ssl --without-hyper --without-zlib --without-brotli --without-zstd --without-default-ssl-backend --without-ca-bundle --without-ca-path --without-ca-fallback --without-libpsl --without-libgsasl --without-librtmp --without-winidn --without-libidn2 --without-nghttp2 --without-ngtcp2 --without-nghttp3 --without-quiche --without-msh3 --without-zsh-functions-dir --without-fish-functions-dir --disable-ftp --disable-file --disable-ldap --disable-ldaps --disable-rtsp --disable-dict --disable-telnet --disable-tftp --disable-pop3 --disable-imap --disable-smb --disable-smtp --disable-gopher --disable-mqtt --disable-manual --disable-ntlm --disable-ntlm-wb --disable-tls-srp --disable-unix-sockets --disable-cookies --disable-socketpair --disable-doh --disable-dateparse --disable-netrc --disable-progress-meter --disable-dnsshuffle --disable-hsts --disable-alt-svc --disable-ares
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
make -j2
cd ../libuv
cd lib && mkdir .libs && cp libcurl.a .libs
cd ../../libuv
mkdir build
cd build
cmake .. -DCMAKE_C_FLAGS='-Os' -DBUILD_TESTING=OFF
+38
View File
@@ -0,0 +1,38 @@
name: clang-tidy
on: [push, 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 16
sudo apt-get install -y clang-tidy-16
clang-tidy-16 --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-16 -DCMAKE_CXX_COMPILER=clang++-16 -DDEV_CLANG_TIDY=ON
- name: Run clang-tidy
run: |
cd src
clang-tidy-16 *.cpp -p ../build -checks=-clang-diagnostic-undefined-internal -warnings-as-errors=* -header-filter=^[^\.]
+32 -4
View File
@@ -1,14 +1,23 @@
name: cppcheck
on: [push, pull_request]
on:
push:
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:
@@ -25,14 +34,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:
@@ -59,9 +81,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
@@ -0,0 +1,36 @@
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
+186 -15
View File
@@ -1,9 +1,13 @@
name: Sync test
on: [push, pull_request]
on:
push:
pull_request:
schedule:
- cron: '17 0/3 * * *'
jobs:
sync-test-ubuntu:
sync-test-ubuntu-tsan:
timeout-minutes: 30
runs-on: ubuntu-22.04
@@ -24,23 +28,186 @@ jobs:
run: |
mkdir build
cd build
cmake .. -DDEV_TEST_SYNC=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
make -j$(nproc)
- name: Run p2pool
timeout-minutes: 15
run: |
cd build
mkdir data
./p2pool --host p2pmd.xmrvsbeast.com --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --no-cache --data-api data --local-api --loglevel 6
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 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
grep 'Synchronization finished successfully' p2pool.log
- name: Archive p2pool.log
uses: actions/upload-artifact@v3
with:
name: p2pool_ubuntu_data
name: p2pool_ubuntu_data_tsan
path: |
build/p2pool.log
build/*.log
build/data/
sync-test-ubuntu-msan:
timeout-minutes: 30
runs-on: ubuntu-22.04
steps:
- 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
- name: Install clang
run: |
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 16
- 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
make -j$(nproc)
cd lib && mkdir .libs && cp libcurl.a .libs
- name: Build libuv
run: |
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
make -j$(nproc)
- name: Build libzmq
run: |
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
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
make -j$(nproc)
- name: Run p2pool
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 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
grep 'Synchronization finished successfully' p2pool.log
- name: Archive p2pool.log
uses: actions/upload-artifact@v3
with:
name: p2pool_ubuntu_data_msan
path: |
build/*.log
build/data/
sync-test-ubuntu-ubsan:
timeout-minutes: 30
runs-on: ubuntu-22.04
steps:
- name: Install dependencies
run: |
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
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 gcc-12 g++-12
- name: Checkout repository
uses: actions/checkout@v3
with:
submodules: true
- name: Build p2pool
run: |
mkdir build
cd build
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_UBSAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12
make -j$(nproc)
- name: Run p2pool
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 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
grep 'Synchronization finished successfully' p2pool.log
- name: Archive p2pool.log
uses: actions/upload-artifact@v3
with:
name: p2pool_ubuntu_data_ubsan
path: |
build/*.log
build/data/
sync-test-ubuntu-asan:
timeout-minutes: 30
runs-on: ubuntu-22.04
steps:
- name: Install dependencies
run: |
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
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 gcc-12 g++-12
- name: Checkout repository
uses: actions/checkout@v3
with:
submodules: true
- name: Build p2pool
run: |
mkdir build
cd build
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_ASAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12
make -j$(nproc)
- name: Run p2pool
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 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
grep 'Synchronization finished successfully' p2pool.log
- name: Archive p2pool.log
uses: actions/upload-artifact@v3
with:
name: p2pool_ubuntu_data_asan
path: |
build/*.log
build/data/
sync-test-macos:
@@ -65,11 +232,13 @@ jobs:
make -j3
- name: Run p2pool
timeout-minutes: 15
run: |
cd build
mkdir data
./p2pool --host p2pmd.xmrvsbeast.com --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --no-cache --data-api data --local-api --loglevel 6
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 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
grep 'Synchronization finished successfully' p2pool.log
- name: Archive p2pool.log
@@ -77,10 +246,10 @@ jobs:
with:
name: p2pool_macos_data
path: |
build/p2pool.log
build/*.log
build/data/
sync-test-windows:
sync-test-windows-debug-asan:
timeout-minutes: 30
runs-on: windows-2022
@@ -102,17 +271,19 @@ jobs:
& "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\msbuild" /m /p:Configuration=Debug p2pool.vcxproj
- name: Run p2pool
timeout-minutes: 15
run: |
cd build/Debug
mkdir data
./p2pool.exe --host p2pmd.xmrvsbeast.com --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --no-cache --data-api data --local-api --loglevel 6
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
findstr /C:"Synchronization finished successfully" p2pool.log
- name: Archive p2pool.log
uses: actions/upload-artifact@v3
with:
name: p2pool_windows_data
name: p2pool_windows_data_debug_asan
path: |
build/Debug/p2pool.log
build/Debug/*.log
build/Debug/data/
+108 -13
View File
@@ -8,6 +8,11 @@ option(WITH_LTO "Use link-time compiler optimization (if linking fails for you,
option(WITH_UPNP "Include UPnP support. If this is turned off, p2pool will not be able to configure port forwarding on UPnP-enabled routers." ON)
option(DEV_TEST_SYNC "[Developer only] Sync test, stop p2pool after sync is complete" OFF)
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)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
@@ -31,6 +36,26 @@ if (DEV_TEST_SYNC)
add_definitions(-DDEV_TEST_SYNC)
endif()
if (DEV_WITH_TSAN)
add_definitions(-DDEV_WITH_TSAN)
endif()
if (DEV_WITH_MSAN)
add_definitions(-DDEV_WITH_MSAN)
endif()
if (DEV_WITH_UBSAN)
add_definitions(-DDEV_WITH_UBSAN)
endif()
if (DEV_WITH_ASAN)
add_definitions(-DDEV_WITH_ASAN)
endif()
if (DEV_CLANG_TIDY)
add_definitions(-DDEV_CLANG_TIDY)
endif()
include(cmake/flags.cmake)
set(HEADERS
@@ -95,7 +120,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()
@@ -129,7 +154,7 @@ if (WITH_UPNP)
endif()
if (WIN32)
set(LIBS ${LIBS} ws2_32 iphlpapi userenv psapi)
set(LIBS ${LIBS} ws2_32 iphlpapi userenv psapi dnsapi dbghelp)
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
set(LIBS ${LIBS} bcrypt)
endif()
@@ -143,9 +168,9 @@ endif()
if (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
find_library(ZMQ_LIBRARY_DEBUG NAMES libzmq-v142-mt-sgd-4_3_5 PATHS "external/lib/libzmq/Debug")
find_library(ZMQ_LIBRARY NAMES libzmq-v142-mt-s-4_3_5 PATHS "external/lib/libzmq/Release")
find_library(UV_LIBRARY_DEBUG NAMES uv_a PATHS "external/lib/libuv/Debug")
find_library(UV_LIBRARY NAMES uv_a PATHS "external/lib/libuv/Release")
find_library(CURL_LIBRARY_DEBUG NAMES libcurld PATHS "external/lib/libcurl/Debug")
find_library(UV_LIBRARY_DEBUG NAMES libuv PATHS "external/lib/libuv/Debug")
find_library(UV_LIBRARY NAMES libuv PATHS "external/lib/libuv/Release")
find_library(CURL_LIBRARY_DEBUG NAMES libcurl-d PATHS "external/lib/libcurl/Debug")
find_library(CURL_LIBRARY NAMES libcurl PATHS "external/lib/libcurl/Release")
add_definitions(-D_DISABLE_VECTOR_ANNOTATION)
add_definitions(-D_DISABLE_STRING_ANNOTATION)
@@ -193,14 +218,69 @@ endif()
add_definitions(/DZMQ_STATIC)
set(CMAKE_REQUIRED_FLAGS "${GENERAL_FLAGS}")
include(CheckCXXSourceCompiles)
check_cxx_source_compiles("int main(){ return __builtin_clzll(1);}" HAVE_BUILTIN_CLZLL)
check_cxx_source_compiles("#include <intrin.h>\n#pragma intrinsic(_BitScanReverse64)\nint main(){unsigned long r;_BitScanReverse64(&r,1);return r;}" HAVE_BITSCANREVERSE64)
check_cxx_source_compiles("#include <sched.h>\nint main(){sched_param param;return sched_setscheduler(0, SCHED_IDLE, &param);}" HAVE_SCHED)
include(CheckCSourceCompiles)
set(CMAKE_REQUIRED_LIBRARIES "resolv")
check_c_source_compiles("int main() { return 0; }" HAVE_RESOLV_LIB)
if (NOT HAVE_RESOLV_LIB)
set(CMAKE_REQUIRED_LIBRARIES)
endif()
check_c_source_compiles("
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <stdio.h>
#include <memory.h>
int main(int argc, char* argv[])
{
if (argc < 2) {
return 1;
}
res_init();
uint8_t answer[4096];
const int anslen = res_query(argv[1], ns_c_in, ns_t_txt, answer, sizeof(answer));
if (anslen > (int) sizeof(answer)) {
return 1;
}
ns_msg handle;
ns_initparse(answer, anslen, &handle);
for (int rrnum = 0, n = ns_msg_count(handle, ns_s_an); rrnum < n; ++rrnum) {
ns_rr rr;
if ((ns_parserr(&handle, ns_s_an, rrnum, &rr) == 0) && (ns_rr_type(rr) == ns_t_txt)) {
for (const uint8_t* data = ns_rr_rdata(rr), *e = data + ns_rr_rdlen(rr); data < e;) {
const int k = *(data++);
if (k && (data + k <= e)) {
char buf[256];
memcpy(buf, data, k);
buf[k] = 0;
puts(buf);
}
data += k;
}
}
}
return 0;
}" HAVE_RES_QUERY)
set(CMAKE_REQUIRED_LIBRARIES)
if (HAVE_BUILTIN_CLZLL)
add_definitions(/DHAVE_BUILTIN_CLZLL)
endif()
@@ -213,13 +293,24 @@ if (HAVE_SCHED)
add_definitions(/DHAVE_SCHED)
endif()
if (HAVE_RES_QUERY)
add_definitions(/DHAVE_RES_QUERY)
if (HAVE_RESOLV_LIB)
set(LIBS ${LIBS} resolv)
endif()
endif()
add_definitions("-DRAPIDJSON_PARSE_DEFAULT_FLAGS=kParseTrailingCommasFlag")
add_executable(${CMAKE_PROJECT_NAME} ${HEADERS} ${SOURCES})
if (STATIC_BINARY OR STATIC_LIBS)
if (WIN32)
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} "${CMAKE_PROJECT_NAME}.exe")
else()
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} ${CMAKE_PROJECT_NAME})
if (NOT (DEV_WITH_TSAN OR DEV_WITH_MSAN OR DEV_WITH_UBSAN OR DEV_WITH_ASAN))
if (WIN32)
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} "${CMAKE_PROJECT_NAME}.exe")
else()
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_STRIP} ${CMAKE_PROJECT_NAME})
endif()
endif()
if (WITH_RANDOMX)
@@ -231,7 +322,7 @@ if (STATIC_BINARY OR STATIC_LIBS)
endif()
if (WIN32)
set(STATIC_LIBS ${STATIC_LIBS} ws2_32 iphlpapi userenv psapi wldap32)
set(STATIC_LIBS ${STATIC_LIBS} ws2_32 iphlpapi userenv psapi dnsapi dbghelp)
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
set(STATIC_LIBS ${STATIC_LIBS} bcrypt)
endif()
@@ -246,9 +337,13 @@ if (STATIC_BINARY OR STATIC_LIBS)
set(STATIC_LIBS ${STATIC_LIBS} pthread)
endif()
if (HAVE_RES_QUERY AND HAVE_RESOLV_LIB)
set(STATIC_LIBS ${STATIC_LIBS} resolv)
endif()
target_link_libraries(${CMAKE_PROJECT_NAME}
"${CMAKE_SOURCE_DIR}/external/src/libzmq/build/lib/libzmq.a"
"${CMAKE_SOURCE_DIR}/external/src/libuv/build/libuv_a.a"
"${CMAKE_SOURCE_DIR}/external/src/libuv/build/libuv.a"
"${CMAKE_SOURCE_DIR}/external/src/curl/lib/.libs/libcurl.a"
${STATIC_LIBS}
)
+3 -7
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,6 +18,7 @@ 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)
@@ -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) + miner(s)
## Features
@@ -62,6 +57,7 @@ Here's the comparison table of the different ways of mining. While pool mining i
* 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
+23 -2
View File
@@ -7,8 +7,26 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
set(GENERAL_FLAGS "-pthread")
if (DEV_WITH_TSAN)
set(GENERAL_FLAGS "${GENERAL_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
endif()
if (DEV_WITH_UBSAN)
set(GENERAL_FLAGS "${GENERAL_FLAGS} -fno-omit-frame-pointer -fsanitize=undefined")
endif()
if (DEV_WITH_ASAN)
set(GENERAL_FLAGS "${GENERAL_FLAGS} -fno-omit-frame-pointer -fsanitize=address")
endif()
set(WARNING_FLAGS "-Wall -Wextra -Wcast-align -Wcast-qual -Wlogical-op -Wstrict-overflow=2 -Wundef -Wformat=2 -Wpointer-arith -Werror")
set(OPTIMIZATION_FLAGS "-Ofast -s")
if (DEV_WITH_TSAN OR DEV_WITH_UBSAN OR DEV_WITH_ASAN)
set(OPTIMIZATION_FLAGS "-O2 -g")
else()
set(OPTIMIZATION_FLAGS "-Ofast -s")
endif()
if (WITH_LTO)
set(OPTIMIZATION_FLAGS "${OPTIMIZATION_FLAGS} -flto -fuse-linker-plugin")
@@ -52,7 +70,10 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
set(GENERAL_FLAGS "-pthread")
set(WARNING_FLAGS "-Wall -Wextra -Wno-undefined-internal -Wunreachable-code-aggressive -Wmissing-prototypes -Wmissing-variable-declarations -Werror")
set(OPTIMIZATION_FLAGS "-Ofast -funroll-loops -fmerge-all-constants")
if (NOT DEV_WITH_MSAN)
set(OPTIMIZATION_FLAGS "-Ofast -funroll-loops -fmerge-all-constants")
endif()
if (WITH_LTO)
set(OPTIMIZATION_FLAGS "${OPTIMIZATION_FLAGS} -flto")
-10
View File
@@ -1,10 +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
+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
@@ -40,6 +40,10 @@
<td>Shares Found</td>
<td>{{ local_stats["shares_found"] }}</td>
</tr>
<tr>
<td>Shares Failed</td>
<td>{{ local_stats["shares_failed"] }}</td>
</tr>
<tr>
<td>Current Effort</td>
<td>{{ local_stats["current_effort"] }}%</td>
@@ -56,6 +60,10 @@
<td>Miner Connections</td>
<td>{{ local_stats["incoming_connections"] }}</td>
</tr>
<tr>
<td>Block reward share</td>
<td>{{ local_stats["block_reward_share_percent"] }}%</td>
</tr>
</tbody>
</table>
</div>
+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
```
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
@@ -1325,7 +1325,7 @@ bool BlockTemplate::submit_sidechain_block(uint32_t template_id, uint32_t nonce,
}
m_poolBlockTemplate->m_verified = true;
if (!m_sidechain->block_seen(*m_poolBlockTemplate)) {
if (!m_sidechain->incoming_block_seen(*m_poolBlockTemplate)) {
m_poolBlockTemplate->m_wantBroadcast = true;
const bool result = m_sidechain->add_block(*m_poolBlockTemplate);
if (!result) {
+7 -13
View File
@@ -204,7 +204,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 +221,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;
@@ -436,19 +436,13 @@ struct raw_ip
FORCEINLINE bool operator!=(const raw_ip& other) const { return !operator==(other); }
FORCEINLINE bool is_localhost() const
{
static constexpr raw_ip localhost_ipv4 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x01 };
static constexpr raw_ip localhost_ipv6 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
FORCEINLINE bool is_localhost() const { return (*this == localhost_ipv4) || (*this == localhost_ipv6); }
FORCEINLINE bool is_ipv4_prefix() const { return memcmp(data, ipv4_prefix, sizeof(ipv4_prefix)) == 0; }
return (*this == localhost_ipv4) || (*this == localhost_ipv6);
}
static const raw_ip localhost_ipv4;
static const raw_ip localhost_ipv6;
FORCEINLINE bool is_ipv4_prefix() const
{
alignas(8) static constexpr uint8_t ipv4_prefix[12] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff };
return memcmp(data, ipv4_prefix, sizeof(ipv4_prefix)) == 0;
}
alignas(8) static const uint8_t ipv4_prefix[12];
};
static_assert(sizeof(raw_ip) == 16, "struct raw_ip has invalid size");
+28 -1
View File
@@ -140,7 +140,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;
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 +155,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
@@ -162,6 +164,7 @@ static cmd cmds[] = {
{ STRCONST("stop_mining"), "", "stop mining", do_stop_mining },
#endif
{ STRCONST("exit"), "", "terminate p2pool", do_exit },
{ STRCONST("version"), "", "show p2pool version", do_version },
{ STRCNULL, NULL, NULL, NULL }
};
@@ -196,6 +199,7 @@ static void do_loglevel(p2pool * /* m_pool */, const char *args)
LOGINFO(0, "log level set to " << level);
}
// cppcheck-suppress constParameterCallback
static void do_addpeers(p2pool *m_pool, const char *args)
{
if (m_pool->p2p_server()) {
@@ -203,6 +207,7 @@ static void do_addpeers(p2pool *m_pool, const char *args)
}
}
// cppcheck-suppress constParameterCallback
static void do_droppeers(p2pool *m_pool, const char * /* args */)
{
if (m_pool->p2p_server()) {
@@ -210,6 +215,7 @@ static void do_droppeers(p2pool *m_pool, const char * /* args */)
}
}
// cppcheck-suppress constParameterCallback
static void do_showpeers(p2pool* m_pool, const char* /* args */)
{
if (m_pool->p2p_server()) {
@@ -217,6 +223,7 @@ static void do_showpeers(p2pool* m_pool, const char* /* args */)
}
}
// cppcheck-suppress constParameterCallback
static void do_showworkers(p2pool* m_pool, const char* /* args */)
{
if (m_pool->stratum_server()) {
@@ -224,6 +231,7 @@ static void do_showworkers(p2pool* m_pool, const char* /* args */)
}
}
// cppcheck-suppress constParameterCallback
static void do_showbans(p2pool* m_pool, const char* /* args */)
{
if (m_pool->stratum_server()) {
@@ -234,6 +242,19 @@ 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)
{
if (m_pool->p2p_server()) {
@@ -242,6 +263,7 @@ static void do_outpeers(p2pool* m_pool, const char* args)
}
}
// cppcheck-suppress constParameterCallback
static void do_inpeers(p2pool* m_pool, const char* args)
{
if (m_pool->p2p_server()) {
@@ -270,6 +292,11 @@ static void do_exit(p2pool *m_pool, const char * /* args */)
m_pool->stop();
}
static void do_version(p2pool* /* m_pool */, const char* /* args */)
{
LOGINFO(0, log::LightCyan() << VERSION);
}
void ConsoleCommands::allocCallback(uv_handle_t* handle, size_t /*suggested_size*/, uv_buf_t* buf)
{
ConsoleCommands* pThis = static_cast<ConsoleCommands*>(handle->data);
+25 -6
View File
@@ -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);
@@ -174,7 +179,11 @@ CurlContext::CurlContext(const std::string& address, int port, const std::string
curl_easy_setopt_checked(m_handle, CURLOPT_WRITEFUNCTION, write_func);
curl_easy_setopt_checked(m_handle, CURLOPT_WRITEDATA, this);
#ifdef DEV_TEST_SYNC
const int timeout = 10;
#else
const int timeout = proxy.empty() ? 1 : 5;
#endif
curl_easy_setopt_checked(m_handle, CURLOPT_URL, m_url.c_str());
curl_easy_setopt_checked(m_handle, CURLOPT_POSTFIELDS, m_req.c_str());
@@ -210,12 +219,17 @@ 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());
tcp_ping = static_cast<double>(m_connectedTime - m_startTime) / 1000.0;
(*m_callback)(m_response.data(), m_response.size(), tcp_ping);
}
delete m_callback;
@@ -228,7 +242,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);
@@ -365,6 +379,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;
@@ -372,11 +388,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()) {
@@ -467,7 +486,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);
}
+37 -47
View File
@@ -154,7 +154,9 @@ public:
memcpy(p + 1, buf + 1, size - 1);
// Ensure memory order in the writer thread
#ifndef DEV_WITH_TSAN
std::atomic_thread_fence(std::memory_order_seq_cst);
#endif
// Mark that everything is written into this log slot
p[0] = buf[0] + 1;
@@ -172,7 +174,7 @@ private:
const uint32_t N = std::min(std::max(std::thread::hardware_concurrency(), 4U), 8U);
char buf[40] = {};
static char buf[40] = {};
log::Stream s(buf);
s << "UV_THREADPOOL_SIZE=" << N << '\0';
@@ -221,7 +223,9 @@ private:
}
// Ensure memory order in the reader thread
#ifndef DEV_WITH_TSAN
std::atomic_thread_fence(std::memory_order_seq_cst);
#endif
uint32_t size = static_cast<uint8_t>(p[2]);
size = (size << 8) + static_cast<uint8_t>(p[1]);
@@ -286,9 +290,9 @@ private:
static FORCEINLINE void strip_colors(char* buf, uint32_t& size)
{
char* p_read = buf;
const char* p_read = buf;
char* p_write = buf;
char* buf_end = buf + size;
const char* buf_end = buf + size;
bool is_color = false;
@@ -329,6 +333,31 @@ static Worker worker;
#endif // P2POOL_LOG_DISABLE
static FORCEINLINE void writeCurrentTime(Stream& s)
{
using namespace std::chrono;
const system_clock::time_point now = system_clock::now();
const time_t t0 = system_clock::to_time_t(now);
tm t;
#ifdef _WIN32
gmtime_s(&t, &t0);
#else
gmtime_r(&t0, &t);
#endif
s.setNumberWidth(2);
s << (t.tm_year + 1900) << '-' << (t.tm_mon + 1) << '-' << t.tm_mday << ' ' << t.tm_hour << ':' << t.tm_min << ':' << t.tm_sec << '.';
const int32_t mcs = time_point_cast<microseconds>(now).time_since_epoch().count() % 1000000;
s.setNumberWidth(4);
s << (mcs / 100);
s.setNumberWidth(1);
}
NOINLINE Writer::Writer(Severity severity) : Stream(m_stackBuf)
{
m_stackBuf[BUF_SIZE] = '\0';
@@ -336,7 +365,7 @@ NOINLINE Writer::Writer(Severity severity) : Stream(m_stackBuf)
m_pos = 3;
*this << Cyan();
writeCurrentTime();
writeCurrentTime(*this);
*this << NoColor() << ' ';
}
@@ -364,53 +393,14 @@ void stop()
#endif
}
NOINLINE void Stream::writeCurrentTime()
{
using namespace std::chrono;
const system_clock::time_point now = system_clock::now();
const time_t t0 = system_clock::to_time_t(now);
tm t;
#ifdef _WIN32
gmtime_s(&t, &t0);
#else
gmtime_r(&t0, &t);
#endif
m_numberWidth = 2;
*this << (t.tm_year + 1900) << '-' << (t.tm_mon + 1) << '-' << t.tm_mday << ' ' << t.tm_hour << ':' << t.tm_min << ':' << t.tm_sec << '.';
const int32_t mcs = time_point_cast<microseconds>(now).time_since_epoch().count() % 1000000;
m_numberWidth = 4;
*this << (mcs / 100);
// cppcheck-suppress redundantAssignment
m_numberWidth = 1;
}
NOINLINE void Stream::Entry<raw_ip>::put(const raw_ip& value, Stream* wrapper)
{
const char* addr_str;
const bool is_ipv4 = value.is_ipv4_prefix();
char addr_str_buf[64];
const char* addr_str = inet_ntop(is_ipv4 ? AF_INET : AF_INET6, value.data + (is_ipv4 ? 12 : 0), addr_str_buf, sizeof(addr_str_buf));
static constexpr uint8_t ipv4_prefix[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255 };
const bool is_v6 = (memcmp(value.data, ipv4_prefix, 12) != 0);
if (is_v6) {
addr_str = inet_ntop(AF_INET6, value.data, addr_str_buf, sizeof(addr_str_buf));
}
else {
addr_str = inet_ntop(AF_INET, value.data + 12, addr_str_buf, sizeof(addr_str_buf));
}
if (addr_str) {
*wrapper << addr_str;
}
else {
*wrapper << "N/A";
}
*wrapper << (addr_str ? addr_str : "N/A");
}
NOINLINE void Stream::Entry<Wallet>::put(const Wallet& w, Stream* wrapper)
+25 -16
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] = '-';
@@ -105,8 +107,6 @@ struct Stream
FORCEINLINE int getNumberWidth() const { return m_numberWidth; }
FORCEINLINE void setNumberWidth(int width) { m_numberWidth = width; }
NOINLINE void writeCurrentTime();
int m_pos;
int m_numberWidth;
char* m_buf;
@@ -146,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*>
@@ -486,16 +492,19 @@ 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
#ifdef P2POOL_LOG_DISABLE
+122 -97
View File
@@ -38,6 +38,7 @@ 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,10 +374,10 @@ 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](void* buf, size_t buf_size)
[client](uint8_t* buf, size_t buf_size)
{
LOGINFO(6, "sending PEER_LIST_REQUEST to " << static_cast<char*>(client->m_addrString));
@@ -384,7 +385,7 @@ void P2PServer::send_peer_list_request(P2PClient* client, uint64_t cur_time)
return 0;
}
*reinterpret_cast<uint8_t*>(buf) = static_cast<uint8_t>(MessageId::PEER_LIST_REQUEST);
*buf = static_cast<uint8_t>(MessageId::PEER_LIST_REQUEST);
return 1;
});
@@ -486,7 +487,21 @@ void P2PServer::load_peer_list()
// Load peers from seed nodes if we're on the default or mini sidechain
auto load_from_seed_nodes = [&saved_list](const char** nodes, int p2p_port) {
for (size_t i = 0; nodes[i][0]; ++i) {
LOGINFO(4, "loading peers from " << nodes[i]);
const char* cur_node = nodes[i];
LOGINFO(4, "loading peers from " << cur_node);
// Prefer DNS TXT records
const bool has_txt = get_dns_txt_records(cur_node, [&saved_list, cur_node](const char* s, size_t n) {
if (!saved_list.empty()) {
saved_list += ',';
}
LOGINFO(4, "added " << log::const_buf(s, n) << " from " << cur_node);
saved_list.append(s, n);
});
if (has_txt) {
continue;
}
addrinfo hints{};
hints.ai_family = AF_UNSPEC;
@@ -494,11 +509,11 @@ void P2PServer::load_peer_list()
hints.ai_flags = AI_ADDRCONFIG;
addrinfo* result;
int err = getaddrinfo(nodes[i], nullptr, &hints, &result);
int err = getaddrinfo(cur_node, nullptr, &hints, &result);
if (err) {
LOGWARN(4, "getaddrinfo failed for " << nodes[i] << ": " << gai_strerror(err) << ", retrying with IPv4 only");
LOGWARN(4, "getaddrinfo failed for " << cur_node << ": " << gai_strerror(err) << ", retrying with IPv4 only");
hints.ai_family = AF_INET;
err = getaddrinfo(nodes[i], nullptr, &hints, &result);
err = getaddrinfo(cur_node, nullptr, &hints, &result);
}
if (err == 0) {
for (addrinfo* r = result; r != NULL; r = r->ai_next) {
@@ -524,7 +539,7 @@ void P2PServer::load_peer_list()
}
if (s.m_pos) {
LOGINFO(4, "added " << static_cast<const char*>(buf) << " from " << nodes[i]);
LOGINFO(4, "added " << static_cast<const char*>(buf) << " from " << cur_node);
if (!saved_list.empty()) {
saved_list += ',';
}
@@ -534,7 +549,7 @@ void P2PServer::load_peer_list()
freeaddrinfo(result);
}
else {
LOGWARN(3, "getaddrinfo failed for " << nodes[i] << ": " << gai_strerror(err));
LOGWARN(3, "getaddrinfo failed for " << cur_node << ": " << gai_strerror(err));
}
}
};
@@ -601,10 +616,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 "
@@ -671,7 +686,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));
@@ -699,7 +714,7 @@ void P2PServer::update_peer_in_list(bool is_v6, const raw_ip& ip, int port)
}
}
void P2PServer::remove_peer_from_list(P2PClient* client)
void P2PServer::remove_peer_from_list(const P2PClient* client)
{
MutexLock lock(m_peerListLock);
@@ -864,10 +879,9 @@ void P2PServer::on_broadcast()
}
for (Broadcast* data : broadcast_queue) {
const bool result = send(client, [client, data](void* buf, size_t buf_size) -> size_t
const bool result = send(client, [client, data](uint8_t* buf, size_t buf_size) -> size_t
{
uint8_t* p0 = reinterpret_cast<uint8_t*>(buf);
uint8_t* p = p0;
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());
@@ -921,7 +935,7 @@ void P2PServer::on_broadcast()
}
}
return p - p0;
return p - buf;
});
if (!result) {
LOGWARN(5, "failed to broadcast to " << static_cast<char*>(client->m_addrString) << ", disconnecting");
@@ -1016,6 +1030,10 @@ int P2PServer::deserialize_block(const uint8_t* buf, uint32_t size, bool compact
void P2PServer::on_timer()
{
if (m_pool->stopped()) {
return;
}
++m_timerCounter;
if (!m_initialPeerList.empty()) {
@@ -1028,7 +1046,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();
}
@@ -1124,7 +1142,7 @@ void P2PServer::download_missing_blocks()
}
const bool result = send(client,
[&id, client](void* buf, size_t buf_size) -> size_t
[&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));
@@ -1132,15 +1150,14 @@ void P2PServer::download_missing_blocks()
return 0;
}
uint8_t* p0 = reinterpret_cast<uint8_t*>(buf);
uint8_t* p = p0;
uint8_t* p = buf;
*(p++) = static_cast<uint8_t>(MessageId::BLOCK_REQUEST);
memcpy(p, id.h, HASH_SIZE);
p += HASH_SIZE;
return p - p0;
return p - buf;
});
if (result) {
@@ -1149,25 +1166,41 @@ void P2PServer::download_missing_blocks()
}
}
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();
}
}
@@ -1195,8 +1228,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)
@@ -1214,6 +1246,8 @@ P2PServer::P2PClient::P2PClient()
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);
@@ -1295,8 +1329,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;
@@ -1604,7 +1637,7 @@ bool P2PServer::P2PClient::send_handshake_challenge()
m_handshakeChallenge = owner->get_random64();
return owner->send(this,
[this, owner](void* buf, size_t buf_size) -> size_t
[this, owner](uint8_t* buf, size_t buf_size) -> size_t
{
LOGINFO(5, "sending HANDSHAKE_CHALLENGE to " << static_cast<char*>(m_addrString));
@@ -1612,8 +1645,7 @@ bool P2PServer::P2PClient::send_handshake_challenge()
return 0;
}
uint8_t* p0 = reinterpret_cast<uint8_t*>(buf);
uint8_t* p = p0;
uint8_t* p = buf;
*(p++) = static_cast<uint8_t>(MessageId::HANDSHAKE_CHALLENGE);
@@ -1627,7 +1659,7 @@ bool P2PServer::P2PClient::send_handshake_challenge()
memcpy(p, &k, sizeof(uint64_t));
p += sizeof(uint64_t);
return p - p0;
return p - buf;
});
}
@@ -1700,7 +1732,7 @@ void P2PServer::P2PClient::send_handshake_solution(const uint8_t (&challenge)[CH
return;
}
uint64_t* value = reinterpret_cast<uint64_t*>(work->solution.h);
const uint64_t* value = reinterpret_cast<uint64_t*>(work->solution.h);
uint64_t high;
umul128(value[HASH_SIZE / sizeof(uint64_t) - 1], CHALLENGE_DIFFICULTY, &high);
@@ -1728,7 +1760,7 @@ void P2PServer::P2PClient::send_handshake_solution(const uint8_t (&challenge)[CH
}
const bool result = work->server->send(work->client,
[work](void* buf, size_t buf_size) -> size_t
[work](uint8_t* buf, size_t buf_size) -> size_t
{
LOGINFO(5, "sending HANDSHAKE_SOLUTION to " << static_cast<char*>(work->client->m_addrString));
@@ -1736,8 +1768,7 @@ void P2PServer::P2PClient::send_handshake_solution(const uint8_t (&challenge)[CH
return 0;
}
uint8_t* p0 = reinterpret_cast<uint8_t*>(buf);
uint8_t* p = p0;
uint8_t* p = buf;
*(p++) = static_cast<uint8_t>(MessageId::HANDSHAKE_SOLUTION);
@@ -1751,7 +1782,7 @@ void P2PServer::P2PClient::send_handshake_solution(const uint8_t (&challenge)[CH
work->client->on_after_handshake(p);
}
return p - p0;
return p - buf;
});
if (result) {
@@ -1847,7 +1878,7 @@ bool P2PServer::P2PClient::on_handshake_solution(const uint8_t* buf)
// Check that incoming connection provided enough PoW
if (m_isIncoming) {
uint64_t* value = reinterpret_cast<uint64_t*>(solution.h);
const uint64_t* value = reinterpret_cast<uint64_t*>(solution.h);
uint64_t high;
umul128(value[HASH_SIZE / sizeof(uint64_t) - 1], CHALLENGE_DIFFICULTY, &high);
@@ -1875,7 +1906,7 @@ bool P2PServer::P2PClient::on_handshake_solution(const uint8_t* buf)
}
return m_owner->send(this,
[this](void* buf, size_t buf_size) -> size_t
[this](uint8_t* buf, size_t buf_size) -> size_t
{
LOGINFO(5, "sending LISTEN_PORT and BLOCK_REQUEST for the chain tip to " << static_cast<char*>(m_addrString));
@@ -1883,10 +1914,9 @@ bool P2PServer::P2PClient::on_handshake_solution(const uint8_t* buf)
return 0;
}
uint8_t* p0 = reinterpret_cast<uint8_t*>(buf);
uint8_t* p = p0;
uint8_t* p = buf;
on_after_handshake(p);
return p - p0;
return p - buf;
});
}
@@ -1905,11 +1935,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(zero_hash);
m_lastBroadcastTimestamp = seconds_since_epoch();
}
@@ -1944,7 +1974,7 @@ bool P2PServer::P2PClient::on_block_request(const uint8_t* buf)
}
return server->send(this,
[this, &blob](void* buf, size_t buf_size) -> size_t
[this, &blob](uint8_t* buf, size_t buf_size) -> size_t
{
LOGINFO(5, "sending BLOCK_RESPONSE to " << static_cast<char*>(m_addrString));
@@ -1954,8 +1984,7 @@ bool P2PServer::P2PClient::on_block_request(const uint8_t* buf)
return 0;
}
uint8_t* p0 = reinterpret_cast<uint8_t*>(buf);
uint8_t* p = p0;
uint8_t* p = buf;
*(p++) = static_cast<uint8_t>(MessageId::BLOCK_RESPONSE);
@@ -1967,21 +1996,25 @@ bool P2PServer::P2PClient::on_block_request(const uint8_t* buf)
p += len;
}
return p - p0;
return p - buf;
});
}
bool P2PServer::P2PClient::on_block_response(const uint8_t* buf, uint32_t size, const hash& 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)) {
server->send_peer_list_request(this, cur_time);
}
return true;
}
const uint64_t received_timestamp = microseconds_since_epoch();
P2PServer* server = static_cast<P2PServer*>(m_owner);
MutexLock lock(server->m_blockLock);
const int result = server->deserialize_block(buf, size, false, received_timestamp);
@@ -2002,7 +2035,6 @@ bool P2PServer::P2PClient::on_block_response(const uint8_t* buf, uint32_t size,
return false;
}
const uint64_t cur_time = seconds_since_epoch();
if (cur_time >= m_nextOutgoingPeerListRequest) {
server->send_peer_list_request(this, cur_time);
}
@@ -2085,46 +2117,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;
}
}
}
@@ -2150,7 +2176,7 @@ bool P2PServer::P2PClient::on_peer_list_request(const uint8_t*)
}
return server->send(this,
[this, &peers, num_selected_peers](void* buf, size_t buf_size) -> size_t
[this, &peers, num_selected_peers](uint8_t* buf, size_t buf_size) -> size_t
{
LOGINFO(6, "sending PEER_LIST_RESPONSE to " << static_cast<char*>(m_addrString));
@@ -2158,8 +2184,7 @@ bool P2PServer::P2PClient::on_peer_list_request(const uint8_t*)
return 0;
}
uint8_t* p0 = reinterpret_cast<uint8_t*>(buf);
uint8_t* p = p0;
uint8_t* p = buf;
*(p++) = static_cast<uint8_t>(MessageId::PEER_LIST_RESPONSE);
*(p++) = static_cast<uint8_t>(num_selected_peers);
@@ -2176,7 +2201,7 @@ bool P2PServer::P2PClient::on_peer_list_request(const uint8_t*)
p += 2;
}
return p - p0;
return p - buf;
});
}
@@ -2200,6 +2225,7 @@ void P2PServer::P2PClient::on_peer_list_response(const uint8_t* buf)
buf += 2;
// Treat IPv4-mapped addresses as regular IPv4 addresses
// cppcheck-suppress uninitvar
if (is_v6 && ip.is_ipv4_prefix()) {
is_v6 = false;
}
@@ -2294,7 +2320,7 @@ bool P2PServer::P2PClient::handle_incoming_block_async(const PoolBlock* block, u
}
}
if (side_chain.block_seen(*block)) {
if (side_chain.incoming_block_seen(*block)) {
LOGINFO(6, "block " << block->m_sidechainId << " (nonce " << block->m_nonce << ", extra_nonce " << block->m_extraNonce << ") was received before, skipping it");
return true;
}
@@ -2391,7 +2417,7 @@ void P2PServer::P2PClient::post_handle_incoming_block(const uint32_t reset_count
}
const bool result = server->send(this,
[this, &id](void* buf, size_t buf_size) -> size_t
[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));
@@ -2399,15 +2425,14 @@ void P2PServer::P2PClient::post_handle_incoming_block(const uint32_t reset_count
return 0;
}
uint8_t* p0 = reinterpret_cast<uint8_t*>(buf);
uint8_t* p = p0;
uint8_t* p = buf;
*(p++) = static_cast<uint8_t>(MessageId::BLOCK_REQUEST);
memcpy(p, id.h, HASH_SIZE);
p += HASH_SIZE;
return p - p0;
return p - buf;
});
if (!result) {
+3 -4
View File
@@ -131,8 +131,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;
@@ -191,7 +190,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();
@@ -201,7 +200,7 @@ private:
void load_peer_list();
void load_monerod_peer_list();
void update_peer_in_list(bool is_v6, const raw_ip& ip, int port);
void remove_peer_from_list(P2PClient* client);
void remove_peer_from_list(const P2PClient* client);
void remove_peer_from_list(const raw_ip& ip);
std::mt19937_64 m_rng;
+159 -85
View File
@@ -69,36 +69,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 +118,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 +186,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 +201,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 +319,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 +341,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 +393,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));
@@ -438,11 +461,13 @@ void p2pool::handle_chain_main(ChainMain& data, const char* extra)
", reward = " << log::Gray() << log::XMRAmount(data.reward));
if (!sidechain_id.empty()) {
PoolBlock* block = side_chain().find_block(sidechain_id);
const PoolBlock* block = side_chain().find_block(sidechain_id);
if (block) {
LOGINFO(0, log::LightGreen() << "BLOCK FOUND: main chain block at height " << data.height << " was mined by this p2pool" << BLOCK_FOUND);
const Wallet& w = params().m_wallet;
const char* who = (block->m_minerWallet == w) ? "you" : "someone else in this p2pool";
LOGINFO(0, log::LightGreen() << "BLOCK FOUND: main chain block at height " << data.height << " was mined by " << who << BLOCK_FOUND);
const uint64_t payout = block->get_payout(w);
if (payout) {
LOGINFO(0, log::LightCyan() << "Your wallet " << log::LightGreen() << w << log::LightCyan() << " got a payout of " << log::LightGreen() << log::XMRAmount(payout) << log::LightCyan() << " in block " << log::LightGreen() << data.height);
@@ -526,7 +551,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);
@@ -601,11 +626,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;
}
@@ -646,7 +673,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) {
@@ -712,14 +739,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)) {
@@ -733,7 +762,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));
@@ -747,8 +776,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();
@@ -760,15 +789,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 {
@@ -776,7 +823,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));
@@ -802,13 +849,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;
}
@@ -855,17 +902,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();
}
}
@@ -917,7 +967,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");
@@ -968,12 +1018,14 @@ void p2pool::parse_get_info_rpc(const char* data, size_t size)
void p2pool::get_version()
{
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](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_version\"}", host.m_rpcLogin, m_params->m_socks5Proxy,
[this](const char* data, size_t size, double)
{
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");
@@ -992,7 +1044,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");
@@ -1036,24 +1088,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();
}
}
@@ -1078,7 +1134,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");
@@ -1128,7 +1184,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;
}
@@ -1170,7 +1226,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;
}
@@ -1562,33 +1618,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()
@@ -1613,7 +1683,11 @@ 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();
+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;
+7 -1
View File
@@ -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"
constexpr char log_category_prefix[] = "P2Pool ";
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;
+4 -3
View File
@@ -447,9 +447,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 +460,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));
+72 -30
View File
@@ -66,6 +66,9 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name)
, m_chainWindowSize(2160)
, m_unclePenalty(20)
, m_precalcFinished(false)
#ifdef DEV_TEST_SYNC
, m_firstPruneTime(0)
#endif
{
if (s_networkType == NetworkType::Invalid) {
s_networkType = type;
@@ -89,7 +92,7 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name)
uv_rwlock_init_checked(&m_sidechainLock);
uv_mutex_init_checked(&m_seenWalletsLock);
uv_mutex_init_checked(&m_seenBlocksLock);
uv_mutex_init_checked(&m_incomingBlocksLock);
uv_rwlock_init_checked(&m_curDifficultyLock);
m_difficultyData.reserve(m_chainWindowSize);
@@ -206,7 +209,7 @@ SideChain::~SideChain()
uv_rwlock_destroy(&m_sidechainLock);
uv_mutex_destroy(&m_seenWalletsLock);
uv_mutex_destroy(&m_seenBlocksLock);
uv_mutex_destroy(&m_incomingBlocksLock);
uv_rwlock_destroy(&m_curDifficultyLock);
for (const auto& it : m_blocksById) {
@@ -466,7 +469,7 @@ bool SideChain::get_shares(const PoolBlock* tip, std::vector<MinerShare>& shares
return true;
}
bool SideChain::block_seen(const PoolBlock& block)
bool SideChain::incoming_block_seen(const PoolBlock& block)
{
// Check if it's some old block
const PoolBlock* tip = m_chainTip;
@@ -476,15 +479,35 @@ bool SideChain::block_seen(const PoolBlock& block)
return true;
}
const uint64_t cur_time = seconds_since_epoch();
// Check if it was received before
MutexLock lock(m_seenBlocksLock);
return !m_seenBlocks.insert(block.get_full_id()).second;
MutexLock lock(m_incomingBlocksLock);
return !m_incomingBlocks.emplace(block.get_full_id(), cur_time).second;
}
void SideChain::unsee_block(const PoolBlock& block)
void SideChain::forget_incoming_block(const PoolBlock& block)
{
MutexLock lock(m_seenBlocksLock);
m_seenBlocks.erase(block.get_full_id());
MutexLock lock(m_incomingBlocksLock);
m_incomingBlocks.erase(block.get_full_id());
}
void SideChain::cleanup_incoming_blocks()
{
const uint64_t cur_time = seconds_since_epoch();
MutexLock lock(m_incomingBlocksLock);
// Forget seen blocks that were added more than 10 minutes ago
hash h;
for (auto i = m_incomingBlocks.begin(); i != m_incomingBlocks.end();) {
if (cur_time < i->second + 10 * 60) {
++i;
}
else {
i = m_incomingBlocks.erase(i);
}
}
}
bool SideChain::add_external_block(PoolBlock& block, std::vector<hash>& missing_blocks)
@@ -542,14 +565,14 @@ bool SideChain::add_external_block(PoolBlock& block, std::vector<hash>& missing_
hash seed;
if (!m_pool->get_seed(block.m_txinGenHeight, seed)) {
LOGWARN(3, "add_external_block mined by " << block.m_minerWallet << ": couldn't get seed hash for mainchain height " << block.m_txinGenHeight);
unsee_block(block);
forget_incoming_block(block);
return false;
}
hash pow_hash;
if (!block.get_pow_hash(m_pool->hasher(), block.m_txinGenHeight, seed, pow_hash)) {
LOGWARN(3, "add_external_block: couldn't get PoW hash for height = " << block.m_sidechainHeight << ", mainchain height " << block.m_txinGenHeight << ". Ignoring it.");
unsee_block(block);
forget_incoming_block(block);
return true;
}
@@ -579,13 +602,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;
@@ -604,12 +635,15 @@ bool SideChain::add_external_block(PoolBlock& block, std::vector<hash>& missing_
}
if (block.m_sidechainId == m_watchBlockSidechainId) {
LOGINFO(0, log::LightGreen() << "BLOCK FOUND: main chain block at height " << m_watchBlock.height << " was mined by this p2pool" << BLOCK_FOUND);
const Wallet& w = m_pool->params().m_wallet;
const char* who = (block.m_minerWallet == w) ? "you" : "someone else in this p2pool";
LOGINFO(0, log::LightGreen() << "BLOCK FOUND: main chain block at height " << m_watchBlock.height << " was mined by " << who << BLOCK_FOUND);
m_watchBlockSidechainId = {};
data = m_watchBlock;
block_found = true;
const Wallet& w = m_pool->params().m_wallet;
const uint64_t payout = block.get_payout(w);
if (payout) {
LOGINFO(0, log::LightCyan() << "Your wallet " << log::LightGreen() << w << log::LightCyan() << " got a payout of " << log::LightGreen() << log::XMRAmount(payout) << log::LightCyan() << " in block " << log::LightGreen() << data.height);
@@ -912,7 +946,7 @@ void SideChain::print_status(bool obtain_sidechain_lock) const
blocks_in_window.emplace(uncle_id);
auto it = m_blocksById.find(uncle_id);
if (it != m_blocksById.end()) {
PoolBlock* uncle = it->second;
const PoolBlock* uncle = it->second;
if (tip_height - uncle->m_sidechainHeight < window_size) {
++total_uncles_in_window;
if (uncle->m_minerWallet == w) {
@@ -988,7 +1022,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())) <<
@@ -1722,6 +1756,7 @@ void SideChain::update_chain_tip(const PoolBlock* block)
}
}
prune_old_blocks();
cleanup_incoming_blocks();
}
}
else if (block->m_sidechainHeight > tip->m_sidechainHeight) {
@@ -1994,7 +2029,6 @@ void SideChain::prune_old_blocks()
auto it2 = m_blocksById.find(block->m_sidechainId);
if (it2 != m_blocksById.end()) {
m_blocksById.erase(it2);
unsee_block(*block);
delete block;
++num_blocks_pruned;
}
@@ -2025,6 +2059,28 @@ void SideChain::prune_old_blocks()
// Pre-calc workers are not needed anymore
finish_precalc();
#ifdef DEV_TEST_SYNC
if (m_firstPruneTime == 0) {
m_firstPruneTime = seconds_since_epoch();
// Test Monero node switching
m_pool->reconnect_to_host();
}
if (cur_time >= m_firstPruneTime + 120) {
LOGINFO(0, log::LightGreen() << "[DEV] Synchronization finished successfully, stopping P2Pool now");
print_status(false);
P2PServer* server = m_pool->p2p_server();
if (server) {
server->print_status();
server->print_bans();
server->show_peers_async();
}
m_pool->print_hosts();
m_pool->stop();
}
#endif
}
}
@@ -2275,20 +2331,6 @@ void SideChain::finish_precalc()
{
LOGERR(1, "exception in finish_precalc(): " << e.what());
}
#ifdef DEV_TEST_SYNC
if (m_pool) {
LOGINFO(0, log::LightGreen() << "[DEV] Synchronization finished successfully, stopping P2Pool now");
print_status(false);
P2PServer* server = m_pool->p2p_server();
if (server) {
server->print_status();
server->print_bans();
server->show_peers_async();
}
m_pool->stop();
}
#endif
}
} // namespace p2pool
+11 -4
View File
@@ -46,8 +46,10 @@ public:
void fill_sidechain_data(PoolBlock& block, std::vector<MinerShare>& shares) const;
bool block_seen(const PoolBlock& block);
void unsee_block(const PoolBlock& block);
bool incoming_block_seen(const PoolBlock& block);
void forget_incoming_block(const PoolBlock& block);
void cleanup_incoming_blocks();
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;
@@ -116,8 +118,9 @@ private:
unordered_map<hash, uint64_t> m_seenWallets;
uint64_t m_seenWalletsLastPruneTime;
uv_mutex_t m_seenBlocksLock;
unordered_set<PoolBlock::full_id> m_seenBlocks;
// Used to quickly cut off multiple broadcasts of the same block by different peers. Only the first broadcast will be processed.
uv_mutex_t m_incomingBlocksLock;
unordered_map<PoolBlock::full_id, uint64_t> m_incomingBlocks;
std::vector<DifficultyData> m_difficultyData;
@@ -152,6 +155,10 @@ private:
std::atomic<bool> m_precalcFinished;
#ifdef DEV_TEST_SYNC
uint64_t m_firstPruneTime;
#endif
hash m_consensusHash;
void launch_precalc(const PoolBlock* block);
+5 -5
View File
@@ -287,7 +287,7 @@ bool StratumServer::on_login(StratumClient* client, uint32_t id, const char* log
client->m_lastJobTarget = target;
const bool result = send(client,
[client, id, &hashing_blob, job_id, blob_size, target, height, &seed_hash](void* buf, size_t buf_size)
[client, id, &hashing_blob, job_id, blob_size, target, height, &seed_hash](uint8_t* buf, size_t buf_size)
{
do {
client->m_rpcId = static_cast<StratumServer*>(client->m_owner)->get_random32();
@@ -377,7 +377,7 @@ bool StratumServer::on_submit(StratumClient* client, uint32_t id, const char* jo
if (!block.get_difficulties(template_id, height, sidechain_height, mainchain_diff, sidechain_diff)) {
LOGWARN(4, "client " << static_cast<char*>(client->m_addrString) << " got a stale share");
return send(client,
[id](void* buf, size_t buf_size)
[id](uint8_t* buf, size_t buf_size)
{
log::Stream s(buf, buf_size);
s << "{\"id\":" << id << ",\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Stale share\"}}\n";
@@ -463,7 +463,7 @@ bool StratumServer::on_submit(StratumClient* client, uint32_t id, const char* jo
LOGWARN(4, "client " << static_cast<char*>(client->m_addrString) << " got a share with invalid job id " << job_id << " (latest job sent has id " << client->m_perConnectionJobId << ')');
const bool result = send(client,
[id](void* buf, size_t buf_size)
[id](uint8_t* buf, size_t buf_size)
{
log::Stream s(buf, buf_size);
s << "{\"id\":" << id << ",\"jsonrpc\":\"2.0\",\"error\":{\"message\":\"Invalid job id\"}}\n";
@@ -773,7 +773,7 @@ void StratumServer::on_blobs_ready()
client->m_lastJobTarget = target;
const bool result = send(client,
[data, target, hashing_blob, job_id](void* buf, size_t buf_size)
[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));
@@ -985,7 +985,7 @@ void StratumServer::on_after_share_found(uv_work_t* req, int /*status*/)
if ((client->m_resetCounter.load() == share->m_clientResetCounter) && (client->m_rpcId == share->m_rpcId)) {
const bool result = server->send(client,
[share](void* buf, size_t buf_size)
[share](uint8_t* buf, size_t buf_size)
{
log::Stream s(buf, buf_size);
switch (share->m_result) {
+25 -21
View File
@@ -27,6 +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)
#ifdef WITH_UPNP
, m_portMapping(0)
#endif
@@ -112,7 +113,7 @@ void TCPServer::parse_address_list_internal(const std::string& address_list, Cal
}
}
const int port = atoi(address.substr(k2 + 1).c_str());
const int port = strtol(address.substr(k2 + 1).c_str(), nullptr, 10);
if ((port > 0) && (port < 65536)) {
callback(is_v6, address, ip, port);
}
@@ -473,7 +474,9 @@ void TCPServer::shutdown_tcp()
}
#endif
uv_thread_join(&m_loopThread);
if (m_loopThreadRunning.load()) {
uv_thread_join(&m_loopThread);
}
uv_mutex_destroy(&m_bansLock);
@@ -573,6 +576,9 @@ bool TCPServer::send_internal(Client* client, Callback<size_t, uint8_t*, size_t>
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();
LOGINFO(1, "event loop started");
@@ -803,16 +809,15 @@ void TCPServer::on_new_client(uv_stream_t* server, Client* client)
}
else {
const bool result = owner->send(client,
[](void* buf, size_t buf_size) -> size_t
[](uint8_t* buf, size_t buf_size) -> size_t
{
if (buf_size < 3) {
return 0;
}
uint8_t* p = reinterpret_cast<uint8_t*>(buf);
p[0] = 5; // Protocol version (SOCKS5)
p[1] = 1; // NMETHODS
p[2] = 0; // Method 0 (no authentication)
buf[0] = 5; // Protocol version (SOCKS5)
buf[1] = 1; // NMETHODS
buf[2] = 0; // Method 0 (no authentication)
return 3;
});
@@ -1076,27 +1081,26 @@ bool TCPServer::Client::on_proxy_handshake(char* data, uint32_t size)
n = 2;
const bool result = m_owner->send(this,
[this](void* buf, size_t buf_size) -> size_t
[this](uint8_t* buf, size_t buf_size) -> size_t
{
if (buf_size < 22) {
return 0;
}
uint8_t* p = reinterpret_cast<uint8_t*>(buf);
p[0] = 5; // Protocol version (SOCKS5)
p[1] = 1; // CONNECT
p[2] = 0; // RESERVED
buf[0] = 5; // Protocol version (SOCKS5)
buf[1] = 1; // CONNECT
buf[2] = 0; // RESERVED
if (m_isV6) {
p[3] = 4; // ATYP
memcpy(p + 4, m_addr.data, 16);
p[20] = static_cast<uint8_t>(m_port >> 8);
p[21] = static_cast<uint8_t>(m_port & 0xFF);
buf[3] = 4; // ATYP
memcpy(buf + 4, m_addr.data, 16);
buf[20] = static_cast<uint8_t>(m_port >> 8);
buf[21] = static_cast<uint8_t>(m_port & 0xFF);
}
else {
p[3] = 1; // ATYP
memcpy(p + 4, m_addr.data + 12, 4);
p[8] = static_cast<uint8_t>(m_port >> 8);
p[9] = static_cast<uint8_t>(m_port & 0xFF);
buf[3] = 1; // ATYP
memcpy(buf + 4, m_addr.data + 12, 4);
buf[8] = static_cast<uint8_t>(m_port >> 8);
buf[9] = static_cast<uint8_t>(m_port & 0xFF);
}
return m_isV6 ? 22 : 10;
@@ -1113,7 +1117,7 @@ bool TCPServer::Client::on_proxy_handshake(char* data, uint32_t size)
case Socks5ProxyState::ConnectRequestSent:
if (m_numRead >= 4) {
uint8_t* p = reinterpret_cast<uint8_t*>(m_readBuf);
const uint8_t* p = reinterpret_cast<uint8_t*>(m_readBuf);
if ((p[0] != 5) && (p[1] != 0) && p[2] != 0) {
LOGWARN(5, "SOCKS5 proxy returned an invalid reply to CONNECT");
return false;
+1
View File
@@ -149,6 +149,7 @@ protected:
int m_defaultBacklog;
uv_thread_t m_loopThread;
std::atomic<bool> m_loopThreadRunning;
static void loop(void* data);
+91 -7
View File
@@ -31,6 +31,15 @@
#include "upnpcommands.h"
#endif
#ifdef _WIN32
#include <WinDNS.h>
#elif defined(HAVE_RES_QUERY)
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <resolv.h>
#endif
static constexpr char log_category_prefix[] = "Util ";
namespace p2pool {
@@ -45,6 +54,11 @@ const char* VERSION = "v" STR2(P2POOL_VERSION_MAJOR) "." STR2(P2POOL_VERSION_MIN
#endif
" on " __DATE__ ")";
const raw_ip raw_ip::localhost_ipv4 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x01 };
const raw_ip raw_ip::localhost_ipv6 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
alignas(8) const uint8_t raw_ip::ipv4_prefix[12] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff };
MinerCallbackHandler::~MinerCallbackHandler() {}
void panic_stop(const char* message)
@@ -462,6 +476,71 @@ bool resolve_host(std::string& host, bool& is_v6)
return true;
}
bool get_dns_txt_records_base(const std::string& host, Callback<void, const char*, size_t>::Base&& callback)
{
if (disable_resolve_host) {
LOGERR(1, "get_dns_txt_records was called with DNS disabled for host " << host);
return false;
}
#ifdef _WIN32
PDNS_RECORD pQueryResults;
if (DnsQuery(host.c_str(), DNS_TYPE_TEXT, DNS_QUERY_STANDARD, NULL, &pQueryResults, NULL) != 0) {
return false;
}
for (PDNS_RECORD p = pQueryResults; p; p = p->pNext) {
for (size_t j = 0; j < p->Data.TXT.dwStringCount; ++j) {
const char* s = p->Data.TXT.pStringArray[j];
const size_t n = strlen(s);
if (n > 0) {
callback(s, n);
}
}
}
DnsRecordListFree(pQueryResults, DnsFreeRecordList);
return true;
#elif defined(HAVE_RES_QUERY)
static const int res_init_result = res_init();
if (res_init_result != 0) {
return false;
}
uint8_t answer[4096] = {};
const int anslen = res_query(host.c_str(), ns_c_in, ns_t_txt, answer, sizeof(answer));
if ((anslen <= 0) || (anslen > static_cast<int>(sizeof(answer)))) {
return false;
}
ns_msg handle{};
if (ns_initparse(answer, anslen, &handle) != 0) {
return false;
}
for (int rrnum = 0, n = ns_msg_count(handle, ns_s_an); rrnum < n; ++rrnum) {
ns_rr rr{};
if ((ns_parserr(&handle, ns_s_an, rrnum, &rr) == 0) && (ns_rr_type(rr) == ns_t_txt)) {
for (const uint8_t* data = ns_rr_rdata(rr), *e = data + ns_rr_rdlen(rr); data < e;) {
const size_t k = *(data++);
if (k && (data + k <= e)) {
callback(reinterpret_cast<const char*>(data), k);
}
data += k;
}
}
}
return true;
#else
(void)host;
(void)callback;
return false;
#endif
}
RandomDeviceSeed RandomDeviceSeed::instance;
struct BSR8
@@ -647,23 +726,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);
}
}
@@ -697,8 +779,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);
}
+6 -1
View File
@@ -35,7 +35,7 @@
namespace p2pool {
#define P2POOL_VERSION_MAJOR 3
#define P2POOL_VERSION_MINOR 3
#define P2POOL_VERSION_MINOR 5
extern const char* VERSION;
@@ -296,6 +296,11 @@ struct Callback
};
};
bool get_dns_txt_records_base(const std::string& host, Callback<void, const char*, size_t>::Base&& callback);
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))); }
} // namespace p2pool
void memory_tracking_start();
+92 -38
View File
@@ -25,7 +25,7 @@ static constexpr char log_category_prefix[] = "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,14 +38,16 @@ ZMQReader::ZMQReader(const std::string& address, uint32_t zmq_port, const std::s
m_proxy.clear();
}
for (uint32_t i = m_publisherPort; i < std::numeric_limits<uint16_t>::max(); ++i) {
try {
m_publisherPort = 0;
char addr_buf[log::Stream::BUF_SIZE + 1];
addr_buf[0] = '\0';
char addr[32];
snprintf(addr, sizeof(addr), "tcp://127.0.0.1:%u", i);
m_publisher.bind(addr);
m_publisherPort = static_cast<uint16_t>(i);
std::random_device rd;
for (uint32_t port = 49152 + (rd() % 16384), i = 0; i < 100; ++i, port = (port < 65535) ? (port + 1) : 49152) {
try {
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;
}
catch (const std::exception& e) {
@@ -58,31 +60,37 @@ ZMQReader::ZMQReader(const std::string& address, uint32_t zmq_port, const std::s
throw zmq::error_t(EFSM);
}
LOGINFO(5, "listening on tcp://127.0.0.1:" << m_publisherPort << " for internal communications");
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);
}
}
@@ -91,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();
@@ -111,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 = {};
@@ -122,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 {
@@ -130,7 +174,7 @@ void ZMQReader::run()
throw zmq::error_t(errno);
}
if (m_finished.load()) {
if (m_stopped) {
break;
}
@@ -144,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) {
@@ -164,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;
@@ -172,23 +217,32 @@ 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;
}
void ZMQReader::parse(char* data, size_t size)
{
char* value = data;
char* end = data + size;
const char* end = data + size;
while ((value < end) && (*value != ':')) {
++value;
@@ -205,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;
}
+22 -5
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);
@@ -45,9 +62,9 @@ private:
zmq::context_t m_context{ 1 };
zmq::socket_t m_publisher{ m_context, ZMQ_PUB };
zmq::socket_t m_subscriber{ m_context, ZMQ_SUB };
uint16_t m_publisherPort = 37891;
std::atomic<bool> m_finished{ false };
std::atomic<bool> m_threadRunning{ false };
uint16_t m_publisherPort = 0;
std::atomic<bool> m_stopped{ false };
std::atomic<bool> m_workerThreadRunning{ false };
TxMempoolData m_tx;
MinerData m_minerData;
+8 -6
View File
@@ -95,7 +95,7 @@ include_directories(src)
include_directories(googletest/googletest/include)
if (WIN32)
set(LIBS ${LIBS} ws2_32 iphlpapi userenv psapi wldap32)
set(LIBS ${LIBS} ws2_32 iphlpapi userenv psapi dnsapi dbghelp)
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
set(LIBS ${LIBS} bcrypt)
endif()
@@ -107,17 +107,17 @@ endif()
if (STATIC_LIBS)
set(ZMQ_LIBRARY "${CMAKE_SOURCE_DIR}/../external/src/libzmq/build/lib/libzmq.a")
set(ZMQ_LIBRARY_DEBUG "${CMAKE_SOURCE_DIR}/../external/src/libzmq/build/lib/libzmq.a")
set(UV_LIBRARY_DEBUG "${CMAKE_SOURCE_DIR}/../external/src/libuv/build/libuv_a.a")
set(UV_LIBRARY "${CMAKE_SOURCE_DIR}/../external/src/libuv/build/libuv_a.a")
set(UV_LIBRARY_DEBUG "${CMAKE_SOURCE_DIR}/../external/src/libuv/build/libuv.a")
set(UV_LIBRARY "${CMAKE_SOURCE_DIR}/../external/src/libuv/build/libuv.a")
set(CURL_LIBRARY_DEBUG "${CMAKE_SOURCE_DIR}/../external/src/curl/lib/.libs/libcurl.a")
set(CURL_LIBRARY "${CMAKE_SOURCE_DIR}/../external/src/curl/lib/.libs/libcurl.a")
else()
if (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
find_library(ZMQ_LIBRARY_DEBUG NAMES libzmq-v142-mt-sgd-4_3_5 PATHS "../external/lib/libzmq/Debug")
find_library(ZMQ_LIBRARY NAMES libzmq-v142-mt-s-4_3_5 PATHS "../external/lib/libzmq/Release")
find_library(UV_LIBRARY_DEBUG NAMES uv_a PATHS "../external/lib/libuv/Debug")
find_library(UV_LIBRARY NAMES uv_a PATHS "../external/lib/libuv/Release")
find_library(CURL_LIBRARY_DEBUG NAMES libcurld PATHS "../external/lib/libcurl/Debug")
find_library(UV_LIBRARY_DEBUG NAMES libuv PATHS "../external/lib/libuv/Debug")
find_library(UV_LIBRARY NAMES libuv PATHS "../external/lib/libuv/Release")
find_library(CURL_LIBRARY_DEBUG NAMES libcurl-d PATHS "../external/lib/libcurl/Debug")
find_library(CURL_LIBRARY NAMES libcurl PATHS "../external/lib/libcurl/Release")
add_definitions(-D_DISABLE_VECTOR_ANNOTATION)
add_definitions(-D_DISABLE_STRING_ANNOTATION)
@@ -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}>)
+1
View File
@@ -92,6 +92,7 @@ TEST(block_template, update)
tpl.update(data, mempool, &wallet);
ASSERT_EQ(b->m_sidechainId, H("272a7eea0b804cf24427528977d221850d0ee06c26e935219a75f180cfbfc7f3"));
ASSERT_EQ(b->m_transactions.size(), 203);
for (size_t i = 1; i < b->m_transactions.size(); ++i) {
Binary file not shown.
+1 -1
View File
@@ -160,7 +160,7 @@ TEST(pool_block, verify)
ASSERT_EQ(b.deserialize(p, n, sidechain, nullptr, false), 0);
p += n;
sidechain.add_block(b);
ASSERT_TRUE(sidechain.add_block(b));
ASSERT_TRUE(sidechain.find_block(b.m_sidechainId) != nullptr);
}
+37
View File
@@ -0,0 +1,37 @@
import socket
import time
import sys
f = open('stratum_dummy' + sys.argv[1] + '.log', 'wb');
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(1)
sock.setblocking(True)
time.sleep(5)
while sock.connect_ex(('127.0.0.1', 3333)) != 0:
f.write(b'.\n')
print('.')
time.sleep(1)
diff = '';
if (sys.argv[1] == '2'):
diff = '+1000';
if (sys.argv[1] == '3'):
diff = '+10000000';
request = '{"id":1,"method":"login","params":{"login":"x' + diff + '"}}\n'
sock.sendall(request.encode('utf-8'))
while True:
data = sock.recv(1024)
if len(data) == 0:
break;
f.write(data)
f.flush()
print(data.decode('utf-8'))
sock.close()
f.close()
+4
View File
@@ -0,0 +1,4 @@
race:p2pool::log::Worker::run()
race:p2pool::log::Worker::write
called_from_lib:libzmq.so
race_top:do_loglevel
+1
View File
@@ -0,0 +1 @@
shift-base:crypto-ops.c
+4
View File
@@ -87,6 +87,10 @@ TEST(util, bsr)
for (uint64_t i = 0, x = 1; i <= 63; ++i, x <<= 1) {
ASSERT_EQ(bsr(x), i);
ASSERT_EQ(bsr_reference(x), i);
const uint64_t y = x | (x - 1);
ASSERT_EQ(bsr(y), i);
ASSERT_EQ(bsr_reference(y), i);
}
}