Compare commits
72 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a8582b2a0f | |||
| 8493dbc47b | |||
| 602b9e2ae9 | |||
| 103a2cbd4f | |||
| e4b11ecab4 | |||
| 781606bec5 | |||
| f4d709c0dd | |||
| 8699e1887c | |||
| bf39319cbb | |||
| e92ce0a5f3 | |||
| f7b90b3808 | |||
| 837a33480e | |||
| 7b02c3d24a | |||
| c59845e746 | |||
| 119782920a | |||
| 30ba38c2b3 | |||
| 87547576de | |||
| 5febb8c4e2 | |||
| ddc6986401 | |||
| c0cabc9739 | |||
| 9a1da5b7c2 | |||
| 5daa2b9dff | |||
| 5988acb12b | |||
| 011d05f7b6 | |||
| 294d1a525e | |||
| e5770a5343 | |||
| 7a65e1feb5 | |||
| 4e55f53fb4 | |||
| 4d944d3dc3 | |||
| 3d3b4837ff | |||
| 8270e0898b | |||
| 2ed63ab3ac | |||
| d99a48d87d | |||
| 27375e7382 | |||
| a81d3c4989 | |||
| b922440fc7 | |||
| 6ca6f2ed3d | |||
| 954b9252c1 | |||
| e355f45544 | |||
| ed32664b9e | |||
| 8619057224 | |||
| 10978c59e4 | |||
| ed56206c30 | |||
| 513c2dfc3b | |||
| 0b544bf55a | |||
| a9d39f0803 | |||
| 2248739dd5 | |||
| b83b691714 | |||
| 887611c9d8 | |||
| 390cf0257e | |||
| 2503dca0e3 | |||
| 8fd45cc977 | |||
| 8d9b9e505e | |||
| 2453c08194 | |||
| f149613d54 | |||
| 2c5cfb6442 | |||
| cfddaf1508 | |||
| 6eff190f87 | |||
| e40c5190b1 | |||
| 2584799415 | |||
| 0463901db7 | |||
| c2704af523 | |||
| 328e9cade9 | |||
| 2b61fff449 | |||
| d8bbe2110e | |||
| 1ef88622d6 | |||
| b1d3fb63f3 | |||
| f44ffd1959 | |||
| e7545db663 | |||
| fcf9d2ad15 | |||
| 7986321a52 | |||
| 8e0f28ee30 |
+25
-17
@@ -19,7 +19,7 @@ jobs:
|
||||
matrix:
|
||||
config:
|
||||
- {arch: x86_64, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline"}
|
||||
- {arch: aarch64, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline"}
|
||||
- {arch: aarch64, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline -mfix-cortex-a53-835769 -mfix-cortex-a53-843419"}
|
||||
|
||||
steps:
|
||||
- name: Setup Alpine Linux
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_BINARY=ON
|
||||
cmake .. -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_BINARY=ON -DARCH_ID=${{ matrix.config.arch }}
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run RandomX tests
|
||||
@@ -83,7 +83,7 @@ jobs:
|
||||
cd tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON
|
||||
cmake .. -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON -DARCH_ID=${{ matrix.config.arch }}
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run tests
|
||||
@@ -246,8 +246,8 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {os: ubuntu-20.04, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections"}
|
||||
- {os: ubuntu-22.04, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections"}
|
||||
- {os: ubuntu-20.04, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -mfix-cortex-a53-835769 -mfix-cortex-a53-843419"}
|
||||
- {os: ubuntu-22.04, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -mfix-cortex-a53-835769 -mfix-cortex-a53-843419"}
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
@@ -345,7 +345,7 @@ jobs:
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_C_FLAGS="-Os ${{ matrix.config.flags }}" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
cmake . -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_C_FLAGS="-Os ${{ matrix.config.flags }}" -DCURL_TARGET_WINDOWS_VERSION=0x0600 -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j$(nproc)
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
@@ -405,9 +405,9 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {vs: Visual Studio 16 2019, os: 2019, msbuild: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\MSBuild\\Current\\Bin\\amd64\\", rx: "ON", upnp: "ON"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, msbuild: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\MSBuild\\Current\\Bin\\amd64\\", rx: "OFF", upnp: "ON"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, msbuild: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\MSBuild\\Current\\Bin\\amd64\\", rx: "OFF", upnp: "OFF"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, vspath: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise", rx: "ON", upnp: "ON"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, vspath: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise", rx: "OFF", upnp: "ON"}
|
||||
- {vs: Visual Studio 16 2019, os: 2019, vspath: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise", rx: "OFF", upnp: "OFF"}
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@@ -423,14 +423,22 @@ jobs:
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "${{ matrix.config.vs }}" -DWITH_RANDOMX=${{ matrix.config.rx }} -DWITH_UPNP=${{ matrix.config.upnp }}
|
||||
& "${{ matrix.config.msbuild }}msbuild" -v:m /m /p:Configuration=Release p2pool.vcxproj
|
||||
& "${{ matrix.config.vspath }}\\MSBuild\\Current\\Bin\\amd64\\msbuild" -v:m /m /p:Configuration=Release p2pool.vcxproj
|
||||
|
||||
- name: Check Windows 7 compatibility
|
||||
shell: cmd
|
||||
run: |
|
||||
call "${{ matrix.config.vspath }}\\VC\\Auxiliary\\Build\\vcvarsall.bat" amd64
|
||||
dumpbin /IMPORTS build/Release/p2pool.exe > 1.txt
|
||||
findstr /R /C:"^ *[0-9A-F][0-9A-F]* [a-zA-Z][a-zA-Z0-9]*$" 1.txt > 2.txt
|
||||
python tests/src/check_win7.py 2.txt
|
||||
|
||||
- name: Run RandomX tests
|
||||
if: matrix.config.rx == 'ON'
|
||||
run: |
|
||||
build/Release/p2pool.exe --test
|
||||
cd build/external/src/RandomX
|
||||
& "${{ matrix.config.msbuild }}msbuild" -v:m /m /p:Configuration=Release randomx-tests.vcxproj
|
||||
& "${{ matrix.config.vspath }}\\MSBuild\\Current\\Bin\\amd64\\msbuild" -v:m /m /p:Configuration=Release randomx-tests.vcxproj
|
||||
Release/randomx-tests.exe
|
||||
|
||||
- name: Build tests
|
||||
@@ -439,7 +447,7 @@ jobs:
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "${{ matrix.config.vs }}"
|
||||
& "${{ matrix.config.msbuild }}msbuild" -v:m /m /p:Configuration=Debug p2pool_tests.vcxproj
|
||||
& "${{ matrix.config.vspath }}\\MSBuild\\Current\\Bin\\amd64\\msbuild" -v:m /m /p:Configuration=Debug p2pool_tests.vcxproj
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
@@ -450,7 +458,7 @@ jobs:
|
||||
- name: Archive binary
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool-msbuild-${{ matrix.config.os }}-randomx-${{ matrix.config.rx }}-upnp-${{ matrix.config.upnp }}.exe
|
||||
name: p2pool-vs-${{ matrix.config.os }}-randomx-${{ matrix.config.rx }}-upnp-${{ matrix.config.upnp }}.exe
|
||||
path: build/Release/p2pool.exe
|
||||
|
||||
build-macos:
|
||||
@@ -533,7 +541,7 @@ jobs:
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-Os -flto -target arm64-apple-macos-11" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
cmake . -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-Os -target arm64-apple-macos-11" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j3
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
@@ -542,7 +550,7 @@ jobs:
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-Os -flto -target arm64-apple-macos-11' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-Os -target arm64-apple-macos-11' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j3
|
||||
|
||||
- name: Build libzmq
|
||||
@@ -550,14 +558,14 @@ jobs:
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-Os -flto -target arm64-apple-macos-11' -DCMAKE_CXX_FLAGS='-Os -flto -target arm64-apple-macos-11' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-Os -target arm64-apple-macos-11' -DCMAKE_CXX_FLAGS='-Os -target arm64-apple-macos-11' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j3
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-flto -target arm64-apple-macos-11" -DCMAKE_CXX_FLAGS="-flto -target arm64-apple-macos-11" -DSTATIC_LIBS=ON -DARCH_ID=aarch64
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-target arm64-apple-macos-11" -DCMAKE_CXX_FLAGS="-target arm64-apple-macos-11" -DSTATIC_LIBS=ON -DWITH_LTO=OFF -DARCH_ID=aarch64
|
||||
make -j3
|
||||
|
||||
- name: Archive binary
|
||||
|
||||
@@ -15,7 +15,7 @@ on:
|
||||
jobs:
|
||||
cppcheck-ubuntu:
|
||||
|
||||
timeout-minutes: 50
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
|
||||
cppcheck-windows:
|
||||
|
||||
timeout-minutes: 50
|
||||
timeout-minutes: 60
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
|
||||
@@ -23,18 +23,41 @@ jobs:
|
||||
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
|
||||
sudo apt install -y git build-essential cmake gcc-12 g++-12
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_C_FLAGS='-fsanitize=thread -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=gcc-12 -DCMAKE_C_FLAGS='-fsanitize=thread -Os -fno-omit-frame-pointer -g' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build libzmq
|
||||
run: |
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_C_FLAGS='-fsanitize=thread -Os -fno-omit-frame-pointer -g' -DCMAKE_CXX_FLAGS='-fsanitize=thread -Os -fno-omit-frame-pointer -g' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_TSAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_C_FLAGS="-flto=2" -DCMAKE_CXX_FLAGS="-flto=2"
|
||||
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_TSAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DWITH_LTO=OFF -DSTATIC_LIBS=ON
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run p2pool
|
||||
@@ -44,7 +67,7 @@ jobs:
|
||||
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
|
||||
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 --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
@@ -129,7 +152,7 @@ jobs:
|
||||
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
|
||||
MSAN_OPTIONS="halt_on_error=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
@@ -175,7 +198,7 @@ jobs:
|
||||
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
|
||||
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 --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
@@ -221,7 +244,7 @@ jobs:
|
||||
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
|
||||
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 --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
@@ -239,7 +262,7 @@ jobs:
|
||||
sync-test-macos:
|
||||
|
||||
timeout-minutes: 30
|
||||
runs-on: macos-13
|
||||
runs-on: macos-11
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@@ -249,14 +272,37 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake libuv zmq libpgm curl pyenv
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install pyenv
|
||||
pyenv install 3:latest
|
||||
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-Os -flto" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j3
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
- name: Build libuv
|
||||
run: |
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-Os -flto' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j3
|
||||
|
||||
- name: Build libzmq
|
||||
run: |
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-Os -flto' -DCMAKE_CXX_FLAGS='-Os -flto' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j3
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DDEV_TEST_SYNC=ON
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-flto" -DCMAKE_CXX_FLAGS="-flto" -DSTATIC_LIBS=ON -DDEV_TEST_SYNC=ON
|
||||
make -j3
|
||||
|
||||
- name: Run p2pool
|
||||
@@ -266,7 +312,7 @@ jobs:
|
||||
python3 ../tests/src/stratum_dummy.py 1 &
|
||||
python3 ../tests/src/stratum_dummy.py 2 &
|
||||
python3 ../tests/src/stratum_dummy.py 3 &
|
||||
./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
|
||||
./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
@@ -303,13 +349,15 @@ jobs:
|
||||
& "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\msbuild" -v:m /m /p:Configuration=Debug p2pool.vcxproj
|
||||
|
||||
- name: Run p2pool
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Auxiliary\\Build\\vcvarsall.bat" amd64
|
||||
cd build/Debug
|
||||
mkdir data
|
||||
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 1"
|
||||
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 2"
|
||||
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 3"
|
||||
./p2pool.exe --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
|
||||
start python ../../tests/src/stratum_dummy.py 1
|
||||
start python ../../tests/src/stratum_dummy.py 2
|
||||
start python ../../tests/src/stratum_dummy.py 3
|
||||
p2pool.exe --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
@@ -352,7 +400,7 @@ jobs:
|
||||
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
|
||||
./p2pool.exe --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
|
||||
@@ -164,6 +164,8 @@ if (WIN32)
|
||||
set(LIBS ${LIBS} bcrypt)
|
||||
endif()
|
||||
add_definitions(-DCURL_STATICLIB)
|
||||
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||
add_definitions(-D_WIN32_WINNT=0x0600)
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
|
||||
set(LIBS ${LIBS} pthread)
|
||||
elseif (NOT APPLE)
|
||||
@@ -357,3 +359,10 @@ if (STATIC_BINARY OR STATIC_LIBS)
|
||||
else()
|
||||
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})
|
||||
endif()
|
||||
|
||||
message(STATUS "Summary of build options:
|
||||
C compiler: ${CMAKE_C_COMPILER} (${CMAKE_C_COMPILER_ID})
|
||||
CXX compiler: ${CMAKE_CXX_COMPILER} (${CMAKE_CXX_COMPILER_ID})
|
||||
C_FLAGS: ${CMAKE_C_FLAGS}
|
||||
CXX_FLAGS: ${CMAKE_CXX_FLAGS}
|
||||
")
|
||||
|
||||
@@ -47,7 +47,7 @@ Here's the comparison table of the different ways of mining. While pool mining i
|
||||
|
||||
* Decentralized: no central server that can be shutdown/blocked. P2Pool uses a separate blockchain to merge mine with Monero. Pool admin can't go rogue or be pressured to do an attack on the network because there is no pool admin!
|
||||
* Permissionless: there is no one to decide who can mine on the pool and who can't.
|
||||
* Trustless: there is no pool wallet, funds are never in custody. All pool blocks pay out to miners immediately.
|
||||
* Trustless: there is no pool wallet, funds are never in custody. All pool blocks pay out to miners directly.
|
||||
* PPLNS payout scheme
|
||||
* **0% fee**
|
||||
* **0 XMR payout fee**
|
||||
@@ -80,7 +80,7 @@ In order to continue mining on P2Pool, you must update both Monero and P2Pool so
|
||||
|
||||
|Monero protocol version|Required Monero software version|Required P2Pool version
|
||||
|-|-|-|
|
||||
|v15, v16 (active after August 13th, 2022)|v0.18.0.0 or newer, v0.18.2.2 recommended|v3.0 or newer
|
||||
|v15, v16 (active after August 13th, 2022)|v0.18.0.0 or newer, v0.18.3.1 is recommended|v3.0 or newer
|
||||
|
||||
## How to mine on P2Pool
|
||||
|
||||
@@ -119,12 +119,12 @@ sudo sysctl vm.nr_hugepages=3072
|
||||
4. Check that ports 18080 (Monero p2p port) and 37889/37888 (P2Pool/P2Pool mini p2p port) are open in your local firewall to ensure better connectivity.
|
||||
5. Start `monerod` with the following command/options:
|
||||
```
|
||||
./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
|
||||
./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 32 --in-peers 64 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
|
||||
```
|
||||
**Note:**
|
||||
The `--zmq-pub` option is required for P2Pool to work properly.
|
||||
|
||||
`--out-peers 64 --in-peers 32` is needed to (1) have many connections to other nodes and (2) limit incoming connection count because it can grow uncontrollably and cause problems when it goes above 1000 (open files limit in Linux). If your network connection's **upload** bandwidth is less than **10 Mbit**, use `--out-peers 16 --in-peers 8` instead.
|
||||
`--out-peers 32 --in-peers 64` is needed to (1) have many connections to other nodes and (2) limit incoming connection count because it can grow uncontrollably and cause problems when it goes above 1000 (open files limit in Linux). If your network connection's **upload** bandwidth is less than **10 Mbit**, use `--out-peers 8 --in-peers 16` instead.
|
||||
|
||||
`--add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080` is needed to have guaranteed good working nodes in your connected peers.
|
||||
|
||||
@@ -187,12 +187,12 @@ nocreate
|
||||
|
||||
8. Start `monerod` with the following command/options:
|
||||
```
|
||||
.\Monero\monerod.exe --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
|
||||
.\Monero\monerod.exe --zmq-pub tcp://127.0.0.1:18083 --out-peers 32 --in-peers 64 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
|
||||
```
|
||||
**Note:**
|
||||
The `--zmq-pub` option is required for P2Pool to work properly.
|
||||
|
||||
`--out-peers 64 --in-peers 32` is needed to (1) have many connections to other nodes and (2) limit incoming connection count because it can grow uncontrollably and cause problems when it goes above 1000 (open files limit in Linux). If your network connection's **upload** bandwidth is less than **10 Mbit**, use `--out-peers 16 --in-peers 8` instead.
|
||||
`--out-peers 32 --in-peers 64` is needed to (1) have many connections to other nodes and (2) limit incoming connection count because it can grow uncontrollably and cause problems when it goes above 1000 (open files limit in Linux). If your network connection's **upload** bandwidth is less than **10 Mbit**, use `--out-peers 8 --in-peers 16` instead.
|
||||
|
||||
`--add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080` is needed to have guaranteed good working nodes in your connected peers.
|
||||
|
||||
@@ -218,7 +218,7 @@ The `--zmq-pub` option is required for P2Pool to work properly.
|
||||
13. *(Optional but highly recommended)* You can create a Quickstart by creating a batch (.bat) file with the following contents and placing it in your P2Pool directory along with `xmrig.exe`.
|
||||
```
|
||||
@ECHO OFF
|
||||
start cmd /k %~dp0\Monero\monerod.exe --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
|
||||
start cmd /k %~dp0\Monero\monerod.exe --zmq-pub tcp://127.0.0.1:18083 --out-peers 32 --in-peers 64 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
|
||||
ECHO Wait until the Monero daemon shows fully synced before continuing. This can take some time. Type 'status' in other window to check progress.
|
||||
PAUSE
|
||||
start cmd /k %~dp0\p2pool.exe --wallet YOUR_WALLET_ADDRESS --mini
|
||||
@@ -244,7 +244,7 @@ cmake ..
|
||||
make -j$(nproc)
|
||||
```
|
||||
|
||||
### [Arch Linux](https://archlinux.org/packages/community/x86_64/p2pool/)
|
||||
### [Arch Linux](https://archlinux.org/packages/extra/x86_64/p2pool/)
|
||||
|
||||
```
|
||||
pacman -S p2pool
|
||||
|
||||
+22
-2
@@ -5,9 +5,24 @@ set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
||||
if(NOT ARCH_ID)
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "")
|
||||
set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" ARCH_ID)
|
||||
endif()
|
||||
|
||||
if (ARCH_ID MATCHES "^(aarch64|arm64|armv8-a)$")
|
||||
set(ARMv8 1)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
set(GENERAL_FLAGS "-pthread")
|
||||
|
||||
if (ARMv8)
|
||||
set(GENERAL_FLAGS "${GENERAL_FLAGS} -mfix-cortex-a53-835769 -mfix-cortex-a53-843419")
|
||||
endif()
|
||||
|
||||
if (DEV_WITH_TSAN)
|
||||
set(GENERAL_FLAGS "${GENERAL_FLAGS} -fno-omit-frame-pointer -fsanitize=thread")
|
||||
endif()
|
||||
@@ -20,7 +35,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
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(WARNING_FLAGS "-Wall -Wextra -Wcast-qual -Wlogical-op -Wstrict-overflow=2 -Wundef -Wformat=2 -Wpointer-arith -Werror")
|
||||
|
||||
if (DEV_WITH_TSAN OR DEV_WITH_UBSAN OR DEV_WITH_ASAN)
|
||||
set(OPTIMIZATION_FLAGS "-O2 -g")
|
||||
@@ -52,7 +67,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
endif()
|
||||
endif()
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
set(GENERAL_FLAGS "/MP")
|
||||
set(GENERAL_FLAGS "/MP /EHa")
|
||||
set(WARNING_FLAGS "/Wall /WX /sdl")
|
||||
set(SECURITY_FLAGS "/GS /guard:cf")
|
||||
set(OPTIMIZATION_FLAGS "/O2 /Oi /Ob2 /Ot /DNDEBUG /GL")
|
||||
@@ -69,11 +84,16 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
if (WIN32)
|
||||
set(GENERAL_FLAGS "")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
||||
else()
|
||||
set(GENERAL_FLAGS "-pthread")
|
||||
endif()
|
||||
|
||||
if (ARMv8)
|
||||
set(GENERAL_FLAGS "${GENERAL_FLAGS} -mfix-cortex-a53-835769")
|
||||
endif()
|
||||
|
||||
set(WARNING_FLAGS "-Wall -Wextra -Wno-undefined-internal -Wunreachable-code-aggressive -Wmissing-prototypes -Wmissing-variable-declarations -Werror")
|
||||
|
||||
if (DEV_WITH_MSAN)
|
||||
|
||||
@@ -111,7 +111,7 @@ class MoneroHelpBox(HelpBoxBase):
|
||||
],
|
||||
"Expose RPC Port": [
|
||||
"Expose restricted RPC API port to your network so external services",
|
||||
"(wallets for example) can connect",
|
||||
"(wallets for example) can connect. Port 18083 (ZMQ-pub) will also be exposed.",
|
||||
"Note: You may choose to open this port in your hosts firewall and/or",
|
||||
" router to allow services outside your network to connect",
|
||||
],
|
||||
|
||||
@@ -109,6 +109,7 @@ services:
|
||||
- 18080:18080/tcp
|
||||
{% if expose_rpc_port == True %}
|
||||
- {{ rpc_port }}:18081/tcp
|
||||
- 18083:18083/tcp
|
||||
{% endif %}
|
||||
volumes:
|
||||
- monero:/home/monero/.bitmonero:rw
|
||||
@@ -119,10 +120,10 @@ services:
|
||||
--zmq-pub tcp://0.0.0.0:18083
|
||||
--disable-dns-checkpoints
|
||||
--enable-dns-blocklist
|
||||
--out-peers 32
|
||||
--in-peers 16
|
||||
--out-peers 16
|
||||
--in-peers 32
|
||||
--add-priority-node=nodes.hashvault.pro:18080
|
||||
--add-priority-node=node.supportxmr.com:18080
|
||||
--add-priority-node=p2pmd.xmrvsbeast.com:18080
|
||||
--non-interactive
|
||||
--p2p-bind-ip=0.0.0.0
|
||||
--p2p-bind-port=18080
|
||||
|
||||
@@ -96,10 +96,10 @@ services:
|
||||
--zmq-pub tcp://0.0.0.0:18083
|
||||
--disable-dns-checkpoints
|
||||
--enable-dns-blocklist
|
||||
--out-peers 32
|
||||
--in-peers 16
|
||||
--out-peers 16
|
||||
--in-peers 32
|
||||
--add-priority-node=nodes.hashvault.pro:18080
|
||||
--add-priority-node=node.supportxmr.com:18080
|
||||
--add-priority-node=p2pmd.xmrvsbeast.com:18080
|
||||
--non-interactive
|
||||
--p2p-bind-ip=0.0.0.0
|
||||
--p2p-bind-port=18080
|
||||
|
||||
+11
-3
@@ -80,16 +80,22 @@ async function load_data() {
|
||||
let pool_stats_req = await fetch('api/pool/stats');
|
||||
let pool_blocks_req = await fetch('api/pool/blocks');
|
||||
let network_stats_req = await fetch('api/network/stats');
|
||||
let latest_release_req = await fetch('api/latest_release');
|
||||
|
||||
let pool_stats = JSON.parse(await pool_stats_req.text());
|
||||
let pool_blocks = JSON.parse(await pool_blocks_req.text());
|
||||
let network_stats = JSON.parse(await network_stats_req.text());
|
||||
let latest_release = JSON.parse(await latest_release_req.text());
|
||||
|
||||
let pool_hashrate = pool_stats.pool_statistics.hashRate / 1e6;
|
||||
let pplns_duration = pool_stats.pool_statistics.pplnsWeight / pool_stats.pool_statistics.hashRate;
|
||||
let min_payout = 0.6 * pool_stats.pool_statistics.sidechainDifficulty / pool_stats.pool_statistics.pplnsWeight;
|
||||
|
||||
document.getElementById("pool_hashrate").innerHTML = pool_hashrate.toFixed(3) + ' MH/s';
|
||||
document.getElementById("pplns_duration").innerHTML = elapsedTimeStr(0, pplns_duration, 0) + ' ' + Math.floor(pplns_duration % 60) + 's';
|
||||
document.getElementById("pool_miners").innerHTML = pool_stats.pool_statistics.miners;
|
||||
document.getElementById("min_payout").innerHTML = min_payout.toFixed(5) + ' XMR';
|
||||
document.getElementById("latest_release").innerHTML = '<a href="' + latest_release.html_url + '" target="_blank">' + latest_release.name + '</a>';
|
||||
|
||||
let ts = Math.floor(Date.now() / 1000);
|
||||
|
||||
@@ -188,6 +194,7 @@ function toggle_menu(name) {
|
||||
</head>
|
||||
<body onload="load_data();setInterval(load_data, 2000);toggle_menu(window.location.hash.substr(1));">
|
||||
<div style="font-size:3rem;text-align:center;">P2Pool</div><div style="font-size:1.1rem;text-align:center;">Decentralized Monero mining pool</div>
|
||||
<div style="font-size:1rem;text-align:center;">Latest release: <span id="latest_release"><a href="https://github.com/SChernykh/p2pool/releases/latest" target="_blank">P2Pool</a></span></div>
|
||||
<br>
|
||||
<table id="main_menu" style="width:100%;margin-left:auto;margin-right:auto;table-layout:fixed;text-align:center;-ms-touch-action:none;touch-action:none;"><tr>
|
||||
<td onclick="toggle_menu('pool')" id="button_pool">Pool</td>
|
||||
@@ -208,7 +215,7 @@ function toggle_menu(name) {
|
||||
<tr><td>Average effort<br><div style="text-align:center;font-size:0.9rem">last 50 blocks</div></td><td><span id="average_effort">N/A</span></td><td></td></tr>
|
||||
<tr><td> </td><td></td><td></td></tr>
|
||||
<tr><td>Fee</td><td>0%</td><td></td></tr>
|
||||
<tr><td>Min payout</td><td>0.0003 XMR</td><td></td></tr>
|
||||
<tr><td>Min payout</td><td><span id="min_payout">0.00027 XMR</span></td><td></td></tr>
|
||||
<tr><td>Payout scheme</td><td><a href="https://en.wikipedia.org/wiki/Mining_pool#Pay-per-last-N-shares" target="_blank">PPLNS</a></td><td></td></tr>
|
||||
<tr><td> </td><td></td><td></td></tr>
|
||||
<tr><td>Statistics</td><td><a href="https://p2pool.observer/" target="_blank">P2Pool observer</a></td><td></td></tr>
|
||||
@@ -241,8 +248,8 @@ It's highly recommended to create a new wallet for mining because wallet address
|
||||
<ul>
|
||||
<li>Download the latest Monero <a href="https://www.getmonero.org/downloads/" target="_blank">release</a>
|
||||
<li>[Optional] Open port <span>18080</span> (Monero p2p port) in your firewall to ensure better connectivity
|
||||
<li>Run <span>./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist</span>
|
||||
<li>If your network connection's upload bandwidth is less than 10 Mbit, use <span>--out-peers 16 --in-peers 8</span> instead.
|
||||
<li>Run <span>./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 32 --in-peers 64 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist</span>
|
||||
<li>If your network connection's upload bandwidth is less than 10 Mbit, use <span>--out-peers 8 --in-peers 16</span> instead.
|
||||
<li>Wait until it's fully synchronized. If you didn't run Monero node before, it can take up to several days to synchronize (5-6 hours on a modern PC with fast SSD and fast Internet connection). You can add <span>--prune-blockchain</span> argument to the command line to run a pruned node (3-4 times less disk usage)
|
||||
</ul></details>
|
||||
|
||||
@@ -260,6 +267,7 @@ It's highly recommended to create a new wallet for mining because wallet address
|
||||
<li>Once P2Pool sync is complete, XMRig should be able to connect to the stratum server on port <span>3333</span>
|
||||
<li>Run <span>./xmrig -o 127.0.0.1:3333</span>. Note that you don't need to specify wallet address for xmrig. Wallet address set in xmrig config will be ignored!
|
||||
<li>To set custom fixed difficulty for your miner (for example, <span>10000</span>), run <span>./xmrig -u x+10000 -o 127.0.0.1:3333</span>
|
||||
<li>To connect another mining rig to your P2Pool node, run <span>./xmrig -o YOUR_P2POOL_NODE_IP:3333</span> on that mining rig
|
||||
</ul></details>
|
||||
|
||||
<details><summary>Checking your progress</summary>
|
||||
|
||||
@@ -80,16 +80,22 @@ async function load_data() {
|
||||
let pool_stats_req = await fetch('api/pool/stats');
|
||||
let pool_blocks_req = await fetch('api/pool/blocks');
|
||||
let network_stats_req = await fetch('api/network/stats');
|
||||
let latest_release_req = await fetch('api/latest_release');
|
||||
|
||||
let pool_stats = JSON.parse(await pool_stats_req.text());
|
||||
let pool_blocks = JSON.parse(await pool_blocks_req.text());
|
||||
let network_stats = JSON.parse(await network_stats_req.text());
|
||||
let latest_release = JSON.parse(await latest_release_req.text());
|
||||
|
||||
let pool_hashrate = pool_stats.pool_statistics.hashRate / 1e6;
|
||||
let pplns_duration = pool_stats.pool_statistics.pplnsWeight / pool_stats.pool_statistics.hashRate;
|
||||
let min_payout = 0.6 * pool_stats.pool_statistics.sidechainDifficulty / pool_stats.pool_statistics.pplnsWeight;
|
||||
|
||||
document.getElementById("pool_hashrate").innerHTML = pool_hashrate.toFixed(3) + ' MH/s';
|
||||
document.getElementById("pplns_duration").innerHTML = elapsedTimeStr(0, pplns_duration, 0) + ' ' + Math.floor(pplns_duration % 60) + 's';
|
||||
document.getElementById("pool_miners").innerHTML = pool_stats.pool_statistics.miners;
|
||||
document.getElementById("min_payout").innerHTML = min_payout.toFixed(5) + ' XMR';
|
||||
document.getElementById("latest_release").innerHTML = '<a href="' + latest_release.html_url + '" target="_blank">' + latest_release.name + '</a>';
|
||||
|
||||
let ts = Math.floor(Date.now() / 1000);
|
||||
|
||||
@@ -188,6 +194,7 @@ function toggle_menu(name) {
|
||||
</head>
|
||||
<body onload="load_data();setInterval(load_data, 2000);toggle_menu(window.location.hash.substr(1));">
|
||||
<div style="font-size:3rem;text-align:center;">P2Pool mini</div><div style="font-size:1.1rem;text-align:center;">Decentralized Monero mining pool</div>
|
||||
<div style="font-size:1rem;text-align:center;">Latest release: <span id="latest_release"><a href="https://github.com/SChernykh/p2pool/releases/latest" target="_blank">P2Pool</a></span></div>
|
||||
<br>
|
||||
<table id="main_menu" style="width:100%;margin-left:auto;margin-right:auto;table-layout:fixed;text-align:center;-ms-touch-action:none;touch-action:none;"><tr>
|
||||
<td onclick="toggle_menu('pool')" id="button_pool">Pool</td>
|
||||
@@ -208,7 +215,7 @@ function toggle_menu(name) {
|
||||
<tr><td>Average effort<br><div style="text-align:center;font-size:0.9rem">last 50 blocks</div></td><td><span id="average_effort">N/A</span></td><td></td></tr>
|
||||
<tr><td> </td><td></td><td></td></tr>
|
||||
<tr><td>Fee</td><td>0%</td><td></td></tr>
|
||||
<tr><td>Min payout</td><td>0.0003 XMR</td><td></td></tr>
|
||||
<tr><td>Min payout</td><td><span id="min_payout">0.00027 XMR</span></td><td></td></tr>
|
||||
<tr><td>Payout scheme</td><td><a href="https://en.wikipedia.org/wiki/Mining_pool#Pay-per-last-N-shares" target="_blank">PPLNS</a></td><td></td></tr>
|
||||
<tr><td> </td><td></td><td></td></tr>
|
||||
<tr><td>Statistics</td><td><a href="https://mini.p2pool.observer/" target="_blank">P2Pool observer</a></td><td></td></tr>
|
||||
@@ -241,8 +248,8 @@ It's highly recommended to create a new wallet for mining because wallet address
|
||||
<ul>
|
||||
<li>Download the latest Monero <a href="https://www.getmonero.org/downloads/" target="_blank">release</a>
|
||||
<li>[Optional] Open port <span>18080</span> (Monero p2p port) in your firewall to ensure better connectivity
|
||||
<li>Run <span>./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist</span>
|
||||
<li>If your network connection's upload bandwidth is less than 10 Mbit, use <span>--out-peers 16 --in-peers 8</span> instead.
|
||||
<li>Run <span>./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 32 --in-peers 64 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist</span>
|
||||
<li>If your network connection's upload bandwidth is less than 10 Mbit, use <span>--out-peers 8 --in-peers 16</span> instead.
|
||||
<li>Wait until it's fully synchronized. If you didn't run Monero node before, it can take up to several days to synchronize (5-6 hours on a modern PC with fast SSD and fast Internet connection). You can add <span>--prune-blockchain</span> argument to the command line to run a pruned node (3-4 times less disk usage)
|
||||
</ul></details>
|
||||
|
||||
@@ -260,6 +267,7 @@ It's highly recommended to create a new wallet for mining because wallet address
|
||||
<li>Once P2Pool sync is complete, XMRig should be able to connect to the stratum server on port <span>3333</span>
|
||||
<li>Run <span>./xmrig -o 127.0.0.1:3333</span>. Note that you don't need to specify wallet address for xmrig. Wallet address set in xmrig config will be ignored!
|
||||
<li>To set custom fixed difficulty for your miner (for example, <span>10000</span>), run <span>./xmrig -u x+10000 -o 127.0.0.1:3333</span>
|
||||
<li>To connect another mining rig to your P2Pool node, run <span>./xmrig -o YOUR_P2POOL_NODE_IP:3333</span> on that mining rig
|
||||
</ul></details>
|
||||
|
||||
<details><summary>Checking your progress</summary>
|
||||
@@ -306,4 +314,4 @@ Donate to support the project:<br><a href="monero:44MnN1f3Eto8DZYUWuE5XZNUtE3vcR
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
+1
-1
Submodule external/src/RandomX updated: f8c8618b56...80d9f08b4f
Vendored
+1
-1
Submodule external/src/libuv updated: 701acd5940...26d43f49ff
Vendored
+1
-1
Submodule external/src/rapidjson updated: 36a5533fde...128cc9359f
@@ -646,7 +646,7 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const
|
||||
|
||||
// Layout: [software id, version, random number, sidechain extra_nonce]
|
||||
uint32_t* sidechain_extra = m_poolBlockTemplate->m_sidechainExtraBuf;
|
||||
sidechain_extra[0] = 0;
|
||||
sidechain_extra[0] = static_cast<uint32_t>(SoftwareID::P2Pool);
|
||||
#ifdef P2POOL_SIDECHAIN_EXTRA_1
|
||||
sidechain_extra[1] = P2POOL_SIDECHAIN_EXTRA_1;
|
||||
#else
|
||||
|
||||
+10
-1
@@ -19,7 +19,7 @@
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#pragma warning(disable : 4005 4061 4324 4365 4464 4619 4625 4626 4668 4710 4711 4804 4820 5039 5045 5220 5246 5264)
|
||||
#pragma warning(disable : 4005 4061 4324 4365 4464 4619 4625 4626 4668 4710 4711 4714 4804 4820 5039 5045 5220 5246 5264)
|
||||
#define FORCEINLINE __forceinline
|
||||
#define NOINLINE __declspec(noinline)
|
||||
#define LIKELY(expression) expression
|
||||
@@ -67,10 +67,18 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#endif
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#elif defined(__linux__) || defined(__unix__) || defined(_POSIX_VERSION) || defined(__MACH__)
|
||||
@@ -89,6 +97,7 @@
|
||||
#endif
|
||||
|
||||
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
|
||||
#define P2POOL_ASAN
|
||||
#define ASAN_POISON_MEMORY_REGION(addr, size) __asan_poison_memory_region((addr), (size))
|
||||
#define ASAN_UNPOISON_MEMORY_REGION(addr, size) __asan_unpoison_memory_region((addr), (size))
|
||||
extern "C" void __asan_poison_memory_region(void const volatile* addr, size_t size);
|
||||
|
||||
+69
-41
@@ -47,7 +47,41 @@ ConsoleCommands::ConsoleCommands(p2pool* pool)
|
||||
LOGINFO(3, "uv_guess_handle returned " << static_cast<int>(stdin_type));
|
||||
if (stdin_type != UV_TTY && stdin_type != UV_NAMED_PIPE) {
|
||||
LOGERR(1, "tty or named pipe is not available");
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
int err;
|
||||
|
||||
if (stdin_type == UV_TTY) {
|
||||
LOGINFO(3, "processing stdin as UV_TTY");
|
||||
err = uv_tty_init(&m_loop, &m_tty, 0, 1);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_tty_init failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
m_stdin_handle = reinterpret_cast<uv_stream_t*>(&m_tty);
|
||||
}
|
||||
else if (stdin_type == UV_NAMED_PIPE) {
|
||||
LOGINFO(3, "processing stdin as UV_NAMED_PIPE");
|
||||
err = uv_pipe_init(&m_loop, &m_stdin_pipe, 0);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_pipe_init failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
m_stdin_handle = reinterpret_cast<uv_stream_t*>(&m_stdin_pipe);
|
||||
err = uv_pipe_open(&m_stdin_pipe, 0);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_pipe_open failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_stdin_handle) {
|
||||
m_stdin_handle->data = this;
|
||||
err = uv_read_start(m_stdin_handle, allocCallback, stdinReadCallback);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_read_start failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
|
||||
std::random_device rd;
|
||||
@@ -67,50 +101,29 @@ ConsoleCommands::ConsoleCommands(p2pool* pool)
|
||||
m_pool->api()->set(p2pool_api::Category::LOCAL, "console",
|
||||
[stdin_type, this](log::Stream& s)
|
||||
{
|
||||
s << "{\"mode\":" << ((stdin_type == UV_TTY) ? "\"tty\"" : "\"pipe\"")
|
||||
<< ",\"tcp_port\":" << m_listenPort
|
||||
<< "}";
|
||||
s << "{\"mode\":\"";
|
||||
|
||||
if (stdin_type == UV_TTY) {
|
||||
s << "tty";
|
||||
}
|
||||
else if (stdin_type == UV_NAMED_PIPE) {
|
||||
s << "pipe";
|
||||
}
|
||||
else {
|
||||
s << static_cast<int>(stdin_type);
|
||||
}
|
||||
|
||||
s << "\",\"tcp_port\":" << m_listenPort << '}';
|
||||
});
|
||||
}
|
||||
|
||||
int err;
|
||||
|
||||
if (stdin_type == UV_TTY) {
|
||||
LOGINFO(3, "processing stdin as UV_TTY");
|
||||
err = uv_tty_init(&m_loop, &m_tty, 0, 1);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_tty_init failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
m_stdin_handle = reinterpret_cast<uv_stream_t*>(&m_tty);
|
||||
}
|
||||
else {
|
||||
LOGINFO(3, "processing stdin as UV_NAMED_PIPE");
|
||||
err = uv_pipe_init(&m_loop, &m_stdin_pipe, 0);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_pipe_init failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
m_stdin_handle = reinterpret_cast<uv_stream_t*>(&m_stdin_pipe);
|
||||
err = uv_pipe_open(&m_stdin_pipe, 0);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_pipe_open failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
m_stdin_handle->data = this;
|
||||
|
||||
err = uv_read_start(m_stdin_handle, allocCallback, stdinReadCallback);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_read_start failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
err = uv_thread_create(&m_loopThread, loop, this);
|
||||
if (err) {
|
||||
LOGERR(1, "failed to start event loop thread, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
m_loopThreadCreated = true;
|
||||
}
|
||||
|
||||
ConsoleCommands::~ConsoleCommands()
|
||||
@@ -120,7 +133,9 @@ ConsoleCommands::~ConsoleCommands()
|
||||
|
||||
void ConsoleCommands::on_shutdown()
|
||||
{
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(m_stdin_handle), nullptr);
|
||||
if (m_stdin_handle) {
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(m_stdin_handle), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
const char* ConsoleCommands::get_log_category() const
|
||||
@@ -187,13 +202,20 @@ static void do_status(p2pool *m_pool, const char * /* args */)
|
||||
if (m_pool->stratum_server()) {
|
||||
m_pool->stratum_server()->print_status();
|
||||
}
|
||||
if (m_pool->p2p_server()) {
|
||||
m_pool->p2p_server()->print_status();
|
||||
|
||||
P2PServer* p2p = m_pool->p2p_server();
|
||||
if (p2p) {
|
||||
p2p->print_status();
|
||||
}
|
||||
|
||||
#ifdef WITH_RANDOMX
|
||||
m_pool->print_miner_status();
|
||||
#endif
|
||||
bkg_jobs_tracker.print_status();
|
||||
|
||||
if (p2p) {
|
||||
p2p->check_for_updates(true);
|
||||
}
|
||||
}
|
||||
|
||||
static void do_loglevel(p2pool * /* m_pool */, const char *args)
|
||||
@@ -297,9 +319,15 @@ static void do_exit(p2pool *m_pool, const char * /* args */)
|
||||
m_pool->stop();
|
||||
}
|
||||
|
||||
static void do_version(p2pool* /* m_pool */, const char* /* args */)
|
||||
// cppcheck-suppress constParameterCallback
|
||||
static void do_version(p2pool* m_pool, const char* /* args */)
|
||||
{
|
||||
LOGINFO(0, log::LightCyan() << VERSION);
|
||||
|
||||
const P2PServer* p2p = m_pool->p2p_server();
|
||||
if (p2p) {
|
||||
p2p->check_for_updates(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ConsoleCommands::allocCallback(uv_handle_t* handle, size_t /*suggested_size*/, uv_buf_t* buf)
|
||||
|
||||
@@ -93,6 +93,7 @@ void generate_keys(hash& pub, hash& sec)
|
||||
ge_p3_tobytes(pub.h, &point);
|
||||
}
|
||||
|
||||
// cppcheck-suppress constParameterReference
|
||||
void generate_keys_deterministic(hash& pub, hash& sec, const uint8_t* entropy, size_t len)
|
||||
{
|
||||
uint32_t counter = 0;
|
||||
|
||||
@@ -176,6 +176,8 @@ CurlContext::CurlContext(const std::string& address, int port, const std::string
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
curl_easy_setopt_checked(m_handle, CURLOPT_BUFFERSIZE, 102400L);
|
||||
|
||||
curl_easy_setopt_checked(m_handle, CURLOPT_WRITEFUNCTION, write_func);
|
||||
curl_easy_setopt_checked(m_handle, CURLOPT_WRITEDATA, this);
|
||||
|
||||
|
||||
+75
-7
@@ -22,6 +22,7 @@
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
#include <stdlib.h>
|
||||
#include <clocale>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4996)
|
||||
@@ -43,8 +44,66 @@ bool CONSOLE_COLORS = true;
|
||||
#ifdef _WIN32
|
||||
static const HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||
static const HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
static const HANDLE hStdErr = GetStdHandle(STD_ERROR_HANDLE);
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(NDEBUG)
|
||||
|
||||
#include <DbgHelp.h>
|
||||
|
||||
#pragma comment(lib, "Dbghelp.lib")
|
||||
|
||||
LONG WINAPI UnhandledExceptionFilter(_In_ _EXCEPTION_POINTERS* exception_pointers)
|
||||
{
|
||||
constexpr size_t MAX_FRAMES = 32;
|
||||
|
||||
void* stack_trace[MAX_FRAMES] = {};
|
||||
DWORD hash;
|
||||
CaptureStackBackTrace(1, MAX_FRAMES, stack_trace, &hash);
|
||||
|
||||
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)] = {};
|
||||
PSYMBOL_INFO pSymbol = reinterpret_cast<PSYMBOL_INFO>(buffer);
|
||||
|
||||
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
||||
|
||||
IMAGEHLP_LINE64 line{};
|
||||
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||
|
||||
const HANDLE h = GetCurrentProcess();
|
||||
|
||||
const uint32_t code = (exception_pointers && exception_pointers->ExceptionRecord) ? exception_pointers->ExceptionRecord->ExceptionCode : 0;
|
||||
|
||||
fprintf(stderr, "\n\nUnhandled exception %X at:\n", code);
|
||||
fflush(stderr);
|
||||
|
||||
for (size_t j = 0; j < MAX_FRAMES; ++j) {
|
||||
const DWORD64 address = reinterpret_cast<DWORD64>(stack_trace[j]);
|
||||
DWORD t = 0;
|
||||
if (SymFromAddr(h, address, nullptr, pSymbol) && SymGetLineFromAddr64(h, address, &t, &line)) {
|
||||
fprintf(stderr, "%s (%s, line %lu)\n", line.FileName, pSymbol->Name, line.LineNumber);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n\n");
|
||||
fflush(stderr);
|
||||
|
||||
// Normal logging might be broken at this point, but try to log it anyway
|
||||
LOGERR(0, "Unhandled exception " << log::Hex(code) << " at:");
|
||||
|
||||
for (size_t j = 0; j < MAX_FRAMES; ++j) {
|
||||
const DWORD64 address = reinterpret_cast<DWORD64>(stack_trace[j]);
|
||||
DWORD t = 0;
|
||||
if (SymFromAddr(h, address, nullptr, pSymbol) && SymGetLineFromAddr64(h, address, &t, &line)) {
|
||||
LOGERR(0, line.FileName << " (" << static_cast<const char*>(pSymbol->Name) << ", line " << static_cast<size_t>(line.LineNumber) << ')');
|
||||
}
|
||||
}
|
||||
|
||||
Sleep(1000);
|
||||
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
#endif // _MSC_VER && !NDEBUG
|
||||
#endif // _WIN32
|
||||
|
||||
class Worker
|
||||
{
|
||||
@@ -61,8 +120,15 @@ public:
|
||||
, m_started{ false }
|
||||
, m_stopped(false)
|
||||
{
|
||||
#if defined(_WIN32) && defined(_MSC_VER) && !defined(NDEBUG)
|
||||
SetUnhandledExceptionFilter(UnhandledExceptionFilter);
|
||||
SymInitialize(GetCurrentProcess(), NULL, TRUE);
|
||||
#endif
|
||||
|
||||
set_main_thread();
|
||||
|
||||
std::setlocale(LC_ALL, "en_001");
|
||||
|
||||
m_logFile.open(log_file_name, std::ios::app | std::ios::binary);
|
||||
|
||||
m_buf.resize(BUF_SIZE);
|
||||
@@ -137,6 +203,10 @@ public:
|
||||
#endif
|
||||
|
||||
m_logFile.close();
|
||||
|
||||
#if defined(_WIN32) && defined(_MSC_VER) && !defined(NDEBUG)
|
||||
SymCleanup(GetCurrentProcess());
|
||||
#endif
|
||||
}
|
||||
|
||||
FORCEINLINE void write(const char* buf, uint32_t size)
|
||||
@@ -242,12 +312,7 @@ private:
|
||||
strip_colors(p, size);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
DWORD k;
|
||||
WriteConsole((severity == 1) ? hStdOut : hStdErr, p, size, &k, nullptr);
|
||||
#else
|
||||
fwrite(p, 1, size, (severity == 1) ? stdout : stderr);
|
||||
#endif
|
||||
|
||||
if (m_logFile.is_open()) {
|
||||
if (c) {
|
||||
@@ -286,6 +351,9 @@ private:
|
||||
m_logFile.open(log_file_name, std::ios::app | std::ios::binary);
|
||||
}
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +38,18 @@ struct Stream
|
||||
enum params : int { BUF_SIZE = 1024 - 1 };
|
||||
|
||||
template<size_t N>
|
||||
explicit FORCEINLINE Stream(char (&buf)[N]) : m_pos(0), m_numberWidth(1), m_buf(buf), m_bufSize(N - 1) {}
|
||||
explicit FORCEINLINE Stream(char (&buf)[N]) : m_pos(0), m_numberWidth(1), m_buf(buf), m_bufSize(N - 1), m_spilled(0) {}
|
||||
|
||||
FORCEINLINE Stream(void* buf, size_t size) : m_pos(0), m_numberWidth(1), m_buf(reinterpret_cast<char*>(buf)), m_bufSize(static_cast<int>(size) - 1) {}
|
||||
FORCEINLINE Stream(void* buf, size_t size) { reset(buf, size); }
|
||||
|
||||
FORCEINLINE void reset(void* buf, size_t size)
|
||||
{
|
||||
m_pos = 0;
|
||||
m_numberWidth = 1;
|
||||
m_buf = reinterpret_cast<char*>(buf);
|
||||
m_bufSize = static_cast<int>(size) - 1;
|
||||
m_spilled = 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct Entry
|
||||
@@ -70,16 +79,13 @@ struct Stream
|
||||
{
|
||||
static_assert(1 < base && base <= 64, "Invalid base");
|
||||
|
||||
const T data_with_sign = data;
|
||||
data = abs(data);
|
||||
const bool negative = (data != data_with_sign);
|
||||
const bool negative = is_negative(data);
|
||||
std::make_unsigned_t<T> udata = abs(data);
|
||||
|
||||
char buf[32];
|
||||
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+/"[udata % base];
|
||||
udata /= base;
|
||||
@@ -98,6 +104,7 @@ struct Stream
|
||||
const int n = static_cast<int>(n0);
|
||||
const int pos = m_pos;
|
||||
if (pos + n > m_bufSize) {
|
||||
m_spilled += n;
|
||||
return;
|
||||
}
|
||||
memcpy(m_buf + pos, buf, n);
|
||||
@@ -111,6 +118,7 @@ struct Stream
|
||||
int m_numberWidth;
|
||||
char* m_buf;
|
||||
int m_bufSize;
|
||||
int m_spilled;
|
||||
};
|
||||
|
||||
struct Writer : public Stream
|
||||
|
||||
+31
-5
@@ -106,7 +106,26 @@ int p2pool_test()
|
||||
return 1;
|
||||
}
|
||||
|
||||
randomx_init_dataset(myDataset, myCache, 0, randomx_dataset_item_count());
|
||||
{
|
||||
const uint32_t numThreads = std::max(std::thread::hardware_concurrency(), 1U);
|
||||
const uint32_t numItems = randomx_dataset_item_count();
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
threads.reserve(numThreads);
|
||||
|
||||
for (uint32_t i = 1; i < numThreads; ++i) {
|
||||
const uint32_t a = (numItems * i) / numThreads;
|
||||
const uint32_t b = (numItems * (i + 1)) / numThreads;
|
||||
|
||||
threads.emplace_back([myDataset, myCache, a, b]() { randomx_init_dataset(myDataset, myCache, a, b - a); });
|
||||
}
|
||||
randomx_init_dataset(myDataset, myCache, 0, numItems / numThreads);
|
||||
|
||||
for (std::thread& t : threads) {
|
||||
t.join();
|
||||
}
|
||||
}
|
||||
|
||||
randomx_release_cache(myCache);
|
||||
|
||||
randomx_vm* myMachine = randomx_create_vm(flags, nullptr, myDataset);
|
||||
@@ -115,14 +134,21 @@ int p2pool_test()
|
||||
return 1;
|
||||
}
|
||||
|
||||
randomx_calculate_hash(myMachine, &myInput, sizeof(myInput) - 1, hash);
|
||||
memset(hash, 0, sizeof(hash));
|
||||
memcpy(hash, myInput, sizeof(myInput));
|
||||
|
||||
for (size_t i = 0; i < 100; ++i) {
|
||||
randomx_calculate_hash(myMachine, &hash, sizeof(hash), hash);
|
||||
}
|
||||
|
||||
char buf[RANDOMX_HASH_SIZE * 2 + 1] = {};
|
||||
p2pool::log::Stream s(buf);
|
||||
s << p2pool::log::hex_buf(hash, RANDOMX_HASH_SIZE);
|
||||
s << p2pool::log::hex_buf(hash, RANDOMX_HASH_SIZE) << '\0';
|
||||
|
||||
if (memcmp(buf, "639183aae1bf4c9a35884cb46b09cad9175f04efd7684e7262a0ac1c2f0b4e3f", RANDOMX_HASH_SIZE * 2) != 0) {
|
||||
printf("Invalid hash calculated\n");
|
||||
constexpr char expected_hash[] = "3b5ecc2bb14f467161a04fe476b541194fba82dbbbfc7c320961f922a0294dee";
|
||||
|
||||
if (memcmp(buf, expected_hash, RANDOMX_HASH_SIZE * 2) != 0) {
|
||||
printf("Invalid hash calculated: expected %s, got %s\n", expected_hash, buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "common.h"
|
||||
|
||||
// Simple memory leak detector for Windows users, works best in RelWithDebInfo configuration.
|
||||
#if defined(_WIN32) && defined(DEV_TRACK_MEMORY)
|
||||
#if defined(_WIN32) && defined(DEV_TRACK_MEMORY) && defined(_MSC_VER) && !defined(NDEBUG)
|
||||
|
||||
#include "uv_util.h"
|
||||
#include <atomic>
|
||||
@@ -270,8 +270,6 @@ void memory_tracking_start()
|
||||
// Trigger std::ostream initialization to avoid reporting it as leaks
|
||||
std::cout << "Memory leak detection = " << 1 << std::endl;
|
||||
|
||||
SymInitialize(GetCurrentProcess(), NULL, TRUE);
|
||||
|
||||
using namespace p2pool;
|
||||
|
||||
uv_replace_allocator(malloc_hook, realloc_hook, calloc_hook, free_hook);
|
||||
@@ -307,8 +305,6 @@ bool memory_tracking_stop()
|
||||
printf("No memory leaks detected\n\n");
|
||||
}
|
||||
|
||||
SymCleanup(h);
|
||||
|
||||
return (total_leaks == 0);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -119,7 +119,7 @@ void Miner::on_block(const BlockTemplate& block)
|
||||
m_nonceTimestamp = cur_ts;
|
||||
m_totalHashes += hash_count;
|
||||
|
||||
if (m_pool->api() && m_pool->params().m_localStats) {
|
||||
if (m_pool->api() && m_pool->params().m_localStats && !m_pool->stopped()) {
|
||||
const double block_reward_share_percent = m_pool->side_chain().get_reward_share(m_pool->params().m_wallet) * 100.0;
|
||||
|
||||
m_pool->api()->set(p2pool_api::Category::LOCAL, "miner",
|
||||
|
||||
+132
-67
@@ -34,8 +34,8 @@
|
||||
LOG_CATEGORY(P2PServer)
|
||||
|
||||
static constexpr char saved_peer_list_file_name[] = "p2pool_peers.txt";
|
||||
static const char* seed_nodes[] = { "seeds.p2pool.io", ""};
|
||||
static const char* seed_nodes_mini[] = { "seeds-mini.p2pool.io", "" };
|
||||
static const char* seed_nodes[] = { "seeds.p2pool.io", "main.p2poolpeers.net", "main.gupax.io", "" };
|
||||
static const char* seed_nodes_mini[] = { "seeds-mini.p2pool.io", "mini.p2poolpeers.net", "mini.gupax.io", "" };
|
||||
|
||||
static constexpr int DEFAULT_BACKLOG = 16;
|
||||
static constexpr uint64_t DEFAULT_BAN_TIME = 600;
|
||||
@@ -59,6 +59,7 @@ P2PServer::P2PServer(p2pool* pool)
|
||||
, m_peerListLastSaved(0)
|
||||
, m_lookForMissingBlocks(true)
|
||||
, m_fastestPeer(nullptr)
|
||||
, m_newP2PoolVersionDetected(false)
|
||||
{
|
||||
m_callbackBuf.resize(P2P_BUF_SIZE);
|
||||
m_blockDeserializeBuf.reserve(MAX_BLOCK_SIZE);
|
||||
@@ -91,6 +92,7 @@ P2PServer::P2PServer(p2pool* pool)
|
||||
uv_mutex_init_checked(&m_broadcastLock);
|
||||
uv_rwlock_init_checked(&m_cachedBlocksLock);
|
||||
uv_mutex_init_checked(&m_connectToPeersLock);
|
||||
uv_mutex_init_checked(&m_showPeersLock);
|
||||
|
||||
int err = uv_async_init(&m_loop, &m_broadcastAsync, on_broadcast);
|
||||
if (err) {
|
||||
@@ -149,6 +151,7 @@ P2PServer::~P2PServer()
|
||||
uv_rwlock_destroy(&m_cachedBlocksLock);
|
||||
|
||||
uv_mutex_destroy(&m_connectToPeersLock);
|
||||
uv_mutex_destroy(&m_showPeersLock);
|
||||
|
||||
delete m_block;
|
||||
delete m_cache;
|
||||
@@ -205,13 +208,12 @@ void P2PServer::store_in_cache(const PoolBlock& block)
|
||||
|
||||
void P2PServer::connect_to_peers_async(const char* peer_list)
|
||||
{
|
||||
{
|
||||
MutexLock lock(m_connectToPeersLock);
|
||||
if (!m_connectToPeersData.empty()) {
|
||||
m_connectToPeersData.append(1, ',');
|
||||
}
|
||||
m_connectToPeersData.append(peer_list);
|
||||
MutexLock lock(m_connectToPeersLock);
|
||||
|
||||
if (!m_connectToPeersData.empty()) {
|
||||
m_connectToPeersData.append(1, ',');
|
||||
}
|
||||
m_connectToPeersData.append(peer_list);
|
||||
|
||||
if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(&m_connectToPeersAsync))) {
|
||||
uv_async_send(&m_connectToPeersAsync);
|
||||
@@ -269,6 +271,9 @@ void P2PServer::update_peer_connections()
|
||||
bool has_good_peers = false;
|
||||
m_fastestPeer = nullptr;
|
||||
|
||||
uint64_t total_outgoing_p2pool = 0;
|
||||
uint64_t newer_version_p2pool = 0;
|
||||
|
||||
unordered_set<raw_ip> connected_clients;
|
||||
|
||||
connected_clients.reserve(m_numConnections);
|
||||
@@ -302,9 +307,17 @@ void P2PServer::update_peer_connections()
|
||||
if ((client->m_pingTime >= 0) && (!m_fastestPeer || (m_fastestPeer->m_pingTime > client->m_pingTime))) {
|
||||
m_fastestPeer = client;
|
||||
}
|
||||
if ((client->m_SoftwareID == SoftwareID::P2Pool) && client->m_SoftwareVersion && !client->m_isIncoming) {
|
||||
++total_outgoing_p2pool;
|
||||
if (client->m_SoftwareVersion > ((P2POOL_VERSION_MAJOR << 16) | P2POOL_VERSION_MINOR)) {
|
||||
++newer_version_p2pool;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_newP2PoolVersionDetected = newer_version_p2pool * 5 > total_outgoing_p2pool;
|
||||
|
||||
std::vector<Peer> peer_list;
|
||||
{
|
||||
MutexLock lock(m_peerListLock);
|
||||
@@ -460,7 +473,7 @@ void P2PServer::save_peer_list()
|
||||
}
|
||||
else {
|
||||
in_addr addr{};
|
||||
memcpy(&addr.s_addr, p.m_addr.data + 12, sizeof(addr.s_addr));
|
||||
memcpy(&addr.s_addr, p.m_addr.data + sizeof(raw_ip::ipv4_prefix), sizeof(addr.s_addr));
|
||||
addr_str = inet_ntop(AF_INET, &addr, addr_str_buf, sizeof(addr_str_buf));
|
||||
if (addr_str) {
|
||||
f << addr_str << ':' << p.m_port << '\n';
|
||||
@@ -594,10 +607,11 @@ void P2PServer::load_peer_list()
|
||||
return;
|
||||
}
|
||||
p.m_isV6 = is_v6;
|
||||
p.normalize();
|
||||
|
||||
bool already_added = false;
|
||||
for (const Peer& peer : m_peerList) {
|
||||
if ((peer.m_isV6 == p.m_isV6) && (peer.m_addr == p.m_addr)) {
|
||||
if (peer.m_addr == p.m_addr) {
|
||||
already_added = true;
|
||||
break;
|
||||
}
|
||||
@@ -699,10 +713,13 @@ void P2PServer::update_peer_in_list(bool is_v6, const raw_ip& ip, int port)
|
||||
{
|
||||
const uint64_t cur_time = seconds_since_epoch();
|
||||
|
||||
Peer peer{ is_v6, ip, port, 0, cur_time };
|
||||
peer.normalize();
|
||||
|
||||
MutexLock lock(m_peerListLock);
|
||||
|
||||
for (Peer& p : m_peerList) {
|
||||
if ((p.m_isV6 == is_v6) && (p.m_addr == ip)) {
|
||||
if (p.m_addr == peer.m_addr) {
|
||||
p.m_port = port;
|
||||
p.m_numFailedConnections = 0;
|
||||
p.m_lastSeen = cur_time;
|
||||
@@ -710,8 +727,8 @@ void P2PServer::update_peer_in_list(bool is_v6, const raw_ip& ip, int port)
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_banned(is_v6, ip)) {
|
||||
m_peerList.emplace_back(Peer{ is_v6, ip, port, 0, cur_time });
|
||||
if (!is_banned(peer.m_isV6, peer.m_addr)) {
|
||||
m_peerList.push_back(peer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -741,6 +758,17 @@ void P2PServer::remove_peer_from_list(const raw_ip& ip)
|
||||
}
|
||||
}
|
||||
|
||||
void P2PServer::Peer::normalize()
|
||||
{
|
||||
if (m_isV6 && m_addr.is_ipv4_prefix()) {
|
||||
m_isV6 = false;
|
||||
}
|
||||
else if (!m_isV6) {
|
||||
// Fill in default bytes for IPv4 addresses
|
||||
memcpy(m_addr.data, raw_ip::ipv4_prefix, sizeof(raw_ip::ipv4_prefix));
|
||||
}
|
||||
}
|
||||
|
||||
void P2PServer::broadcast(const PoolBlock& block, const PoolBlock* parent)
|
||||
{
|
||||
MinerData miner_data = m_pool->miner_data();
|
||||
@@ -827,33 +855,21 @@ void P2PServer::broadcast(const PoolBlock& block, const PoolBlock* parent)
|
||||
|
||||
LOGINFO(5, "Broadcasting block " << block.m_sidechainId << " (height " << block.m_sidechainHeight << "): " << data->compact_blob.size() << '/' << data->pruned_blob.size() << '/' << data->blob.size() << " bytes (compact/pruned/full)");
|
||||
|
||||
{
|
||||
MutexLock lock(m_broadcastLock);
|
||||
m_broadcastQueue.push_back(data);
|
||||
}
|
||||
MutexLock lock(m_broadcastLock);
|
||||
|
||||
if (uv_is_closing(reinterpret_cast<uv_handle_t*>(&m_broadcastAsync))) {
|
||||
delete data;
|
||||
return;
|
||||
}
|
||||
|
||||
m_broadcastQueue.push_back(data);
|
||||
|
||||
const int err = uv_async_send(&m_broadcastAsync);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_async_send failed, error " << uv_err_name(err));
|
||||
|
||||
bool found = false;
|
||||
{
|
||||
MutexLock lock(m_broadcastLock);
|
||||
|
||||
auto it = std::find(m_broadcastQueue.begin(), m_broadcastQueue.end(), data);
|
||||
if (it != m_broadcastQueue.end()) {
|
||||
found = true;
|
||||
m_broadcastQueue.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
delete data;
|
||||
}
|
||||
m_broadcastQueue.pop_back();
|
||||
delete data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -988,6 +1004,8 @@ void P2PServer::print_status()
|
||||
|
||||
void P2PServer::show_peers_async()
|
||||
{
|
||||
MutexLock lock(m_showPeersLock);
|
||||
|
||||
if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(&m_showPeersAsync))) {
|
||||
uv_async_send(&m_showPeersAsync);
|
||||
}
|
||||
@@ -1075,6 +1093,7 @@ void P2PServer::on_timer()
|
||||
update_peer_connections();
|
||||
check_host();
|
||||
check_block_template();
|
||||
check_for_updates();
|
||||
api_update_local_stats();
|
||||
}
|
||||
|
||||
@@ -1218,7 +1237,7 @@ void P2PServer::check_host()
|
||||
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");
|
||||
LOGERR(1, "Host " << host.m_displayName << " seems to be stuck, reconnecting");
|
||||
m_pool->reconnect_to_host();
|
||||
return;
|
||||
}
|
||||
@@ -1231,7 +1250,7 @@ void P2PServer::check_host()
|
||||
if (cur_time >= last_active + 300) {
|
||||
const uint64_t dt = static_cast<uint64_t>(cur_time - last_active);
|
||||
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!!!");
|
||||
LOGERR(1, "no ZMQ messages received from host " << host.m_displayName << " in the last " << dt << " seconds, check your monerod/p2pool/network/firewall setup!!!");
|
||||
m_pool->reconnect_to_host();
|
||||
}
|
||||
}
|
||||
@@ -1249,6 +1268,27 @@ void P2PServer::check_block_template()
|
||||
}
|
||||
}
|
||||
|
||||
void P2PServer::check_for_updates(bool forced) const
|
||||
{
|
||||
#ifdef DEV_TEST_SYNC
|
||||
constexpr uint64_t check_interval = 60;
|
||||
#else
|
||||
constexpr uint64_t check_interval = 3600;
|
||||
#endif
|
||||
|
||||
if (!forced && (m_timerCounter % (check_interval / m_timerInterval) != 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const SideChain& s = m_pool->side_chain();
|
||||
|
||||
if ((forced || s.precalcFinished()) && m_newP2PoolVersionDetected && s.p2pool_update_available()) {
|
||||
LOGINFO(0, log::LightCyan() << "********************************************************************************");
|
||||
LOGINFO(0, log::LightCyan() << "* An updated P2Pool version is available, visit p2pool.io for more information *");
|
||||
LOGINFO(0, log::LightCyan() << "********************************************************************************");
|
||||
}
|
||||
}
|
||||
|
||||
P2PServer::P2PClient::P2PClient()
|
||||
: Client(m_p2pReadBuf, sizeof(m_p2pReadBuf))
|
||||
, m_peerId(0)
|
||||
@@ -1266,7 +1306,7 @@ P2PServer::P2PClient::P2PClient()
|
||||
, m_peerListPendingRequests(0)
|
||||
, m_protocolVersion(PROTOCOL_VERSION_1_0)
|
||||
, m_SoftwareVersion(0)
|
||||
, m_SoftwareID(0)
|
||||
, m_SoftwareID(SoftwareID::P2Pool)
|
||||
, m_pingTime(-1)
|
||||
, m_lastAlive(0)
|
||||
, m_lastBroadcastTimestamp(0)
|
||||
@@ -1283,14 +1323,23 @@ void P2PServer::on_shutdown()
|
||||
|
||||
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);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_connectToPeersAsync), nullptr);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_showPeersAsync), nullptr);
|
||||
{
|
||||
MutexLock lock(m_broadcastLock);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_broadcastAsync), nullptr);
|
||||
}
|
||||
{
|
||||
MutexLock lock(m_connectToPeersLock);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_connectToPeersAsync), nullptr);
|
||||
}
|
||||
{
|
||||
MutexLock lock(m_showPeersLock);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_showPeersAsync), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void P2PServer::api_update_local_stats()
|
||||
{
|
||||
if (!m_pool->api() || !m_pool->params().m_localStats || ((m_timerCounter % 30) != 5)) {
|
||||
if (!m_pool->api() || !m_pool->params().m_localStats || m_pool->stopped() || ((m_timerCounter % 30) != 5)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1299,9 +1348,15 @@ void P2PServer::api_update_local_stats()
|
||||
{
|
||||
const uint64_t cur_time = seconds_since_epoch();
|
||||
|
||||
size_t peer_list_size;
|
||||
{
|
||||
MutexLock lock(m_peerListLock);
|
||||
peer_list_size = m_peerList.size();
|
||||
}
|
||||
|
||||
s << "{\"connections\":" << m_numConnections.load()
|
||||
<< ",\"incoming_connections\":" << m_numIncomingConnections.load()
|
||||
<< ",\"peer_list_size\":" << m_peerList.size()
|
||||
<< ",\"peer_list_size\":" << peer_list_size
|
||||
<< ",\"peers\":[";
|
||||
|
||||
bool first = true;
|
||||
@@ -1327,10 +1382,6 @@ void P2PServer::api_update_local_stats()
|
||||
<< static_cast<char*>(client->m_addrString)
|
||||
<< '"';
|
||||
|
||||
if (s.m_pos + 128 >= s.m_bufSize) {
|
||||
break;
|
||||
}
|
||||
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
@@ -1368,7 +1419,7 @@ void P2PServer::P2PClient::reset()
|
||||
m_peerListPendingRequests = 0;
|
||||
m_protocolVersion = PROTOCOL_VERSION_1_0;
|
||||
m_SoftwareVersion = 0;
|
||||
m_SoftwareID = 0;
|
||||
m_SoftwareID = SoftwareID::P2Pool;
|
||||
m_pingTime = -1;
|
||||
m_blockPendingRequests.clear();
|
||||
m_lastAlive = 0;
|
||||
@@ -2248,7 +2299,8 @@ bool P2PServer::P2PClient::on_peer_list_request(const uint8_t*)
|
||||
peers[0] = {};
|
||||
*reinterpret_cast<uint32_t*>(peers[0].m_addr.data) = SUPPORTED_PROTOCOL_VERSION;
|
||||
*reinterpret_cast<uint32_t*>(peers[0].m_addr.data + 4) = (P2POOL_VERSION_MAJOR << 16) | P2POOL_VERSION_MINOR;
|
||||
*reinterpret_cast<uint32_t*>(peers[0].m_addr.data + 12) = 0xFFFFFFFFU;
|
||||
*reinterpret_cast<uint32_t*>(peers[0].m_addr.data + 8) = static_cast<uint32_t>(SoftwareID::P2Pool);
|
||||
*reinterpret_cast<uint32_t*>(peers[0].m_addr.data + sizeof(raw_ip::ipv4_prefix)) = 0xFFFFFFFFU;
|
||||
peers[0].m_port = 0xFFFF;
|
||||
|
||||
if (num_selected_peers == 0) {
|
||||
@@ -2317,7 +2369,7 @@ void P2PServer::P2PClient::on_peer_list_response(const uint8_t* buf)
|
||||
// Ignore 0.0.0.0/8 (special-purpose range for "this network") and 224.0.0.0/3 (IP multicast and reserved ranges)
|
||||
|
||||
// Check for protocol version message
|
||||
if ((*reinterpret_cast<uint32_t*>(ip.data + 12) == 0xFFFFFFFFU) && (port == 0xFFFF)) {
|
||||
if ((*reinterpret_cast<uint32_t*>(ip.data + sizeof(raw_ip::ipv4_prefix)) == 0xFFFFFFFFU) && (port == 0xFFFF)) {
|
||||
const uint32_t version = *reinterpret_cast<uint32_t*>(ip.data);
|
||||
|
||||
// Clients with different major protocol versions communicate using v1.0 protocol
|
||||
@@ -2330,24 +2382,30 @@ void P2PServer::P2PClient::on_peer_list_response(const uint8_t* buf)
|
||||
}
|
||||
|
||||
m_SoftwareVersion = *reinterpret_cast<uint32_t*>(ip.data + 4);
|
||||
m_SoftwareID = *reinterpret_cast<uint32_t*>(ip.data + 8);
|
||||
const uint32_t id_value = *reinterpret_cast<uint32_t*>(ip.data + 8);
|
||||
m_SoftwareID = get_software_id(id_value);
|
||||
|
||||
LOGINFO(5, "peer " << log::Gray() << static_cast<char*>(m_addrString) << log::NoColor()
|
||||
<< " supports protocol version " << (m_protocolVersion >> 16) << '.' << (m_protocolVersion & 0xFFFF)
|
||||
<< ", runs " << software_name() << " v" << (m_SoftwareVersion >> 16) << '.' << (m_SoftwareVersion & 0xFFFF)
|
||||
);
|
||||
|
||||
if (m_SoftwareID == SoftwareID::Unknown) {
|
||||
LOGWARN(4, "peer " << log::Gray() << static_cast<char*>(m_addrString) << log::NoColor()
|
||||
<< "runs an unknown software with id = " << log::Hex(id_value)
|
||||
);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fill in default bytes for IPv4 addresses
|
||||
memset(ip.data, 0, 10);
|
||||
ip.data[10] = 0xFF;
|
||||
ip.data[11] = 0xFF;
|
||||
memcpy(ip.data, raw_ip::ipv4_prefix, sizeof(raw_ip::ipv4_prefix));
|
||||
}
|
||||
|
||||
bool already_added = false;
|
||||
for (Peer& p : server->m_peerList) {
|
||||
if ((p.m_isV6 == is_v6) && (p.m_addr == ip)) {
|
||||
if (p.m_addr == ip) {
|
||||
already_added = true;
|
||||
p.m_lastSeen = cur_time;
|
||||
break;
|
||||
@@ -2355,7 +2413,9 @@ void P2PServer::P2PClient::on_peer_list_response(const uint8_t* buf)
|
||||
}
|
||||
|
||||
if (!already_added && !server->is_banned(is_v6, ip)) {
|
||||
server->m_peerList.emplace_back(Peer{ is_v6, ip, port, 0, cur_time });
|
||||
Peer p{ is_v6, ip, port, 0, cur_time };
|
||||
p.normalize();
|
||||
server->m_peerList.push_back(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2474,9 +2534,10 @@ bool P2PServer::P2PClient::handle_incoming_block_async(const PoolBlock* block, u
|
||||
bool client_isV6;
|
||||
raw_ip client_ip;
|
||||
std::vector<hash> missing_blocks;
|
||||
bool result;
|
||||
};
|
||||
|
||||
Work* work = new Work{ {}, *block, this, server, m_resetCounter.load(), m_isV6, m_addr, {} };
|
||||
Work* work = new Work{ {}, *block, this, server, m_resetCounter.load(), m_isV6, m_addr, {}, true };
|
||||
work->req.data = work;
|
||||
|
||||
const int err = uv_queue_work(&server->m_loop, &work->req,
|
||||
@@ -2484,12 +2545,12 @@ bool P2PServer::P2PClient::handle_incoming_block_async(const PoolBlock* block, u
|
||||
{
|
||||
BACKGROUND_JOB_START(P2PServer::handle_incoming_block_async);
|
||||
Work* work = reinterpret_cast<Work*>(req->data);
|
||||
work->client->handle_incoming_block(work->server->m_pool, work->block, work->client_reset_counter, work->client_isV6, work->client_ip, work->missing_blocks);
|
||||
work->client->handle_incoming_block(work->server->m_pool, work->block, work->missing_blocks, work->result);
|
||||
},
|
||||
[](uv_work_t* req, int /*status*/)
|
||||
{
|
||||
Work* work = reinterpret_cast<Work*>(req->data);
|
||||
work->client->post_handle_incoming_block(work->block, work->client_reset_counter, work->missing_blocks);
|
||||
work->client->post_handle_incoming_block(work->server->m_pool, work->block, work->client_reset_counter, work->client_isV6, work->client_ip, work->missing_blocks, work->result);
|
||||
delete work;
|
||||
BACKGROUND_JOB_STOP(P2PServer::handle_incoming_block_async);
|
||||
});
|
||||
@@ -2503,11 +2564,18 @@ bool P2PServer::P2PClient::handle_incoming_block_async(const PoolBlock* block, u
|
||||
return true;
|
||||
}
|
||||
|
||||
void P2PServer::P2PClient::handle_incoming_block(p2pool* pool, PoolBlock& block, const uint32_t reset_counter, bool is_v6, const raw_ip& addr, std::vector<hash>& missing_blocks)
|
||||
void P2PServer::P2PClient::handle_incoming_block(p2pool* pool, PoolBlock& block, std::vector<hash>& missing_blocks, bool& result)
|
||||
{
|
||||
if (!pool->side_chain().add_external_block(block, missing_blocks)) {
|
||||
result = pool->side_chain().add_external_block(block, missing_blocks);
|
||||
}
|
||||
|
||||
void P2PServer::P2PClient::post_handle_incoming_block(p2pool* pool, const PoolBlock& block, const uint32_t reset_counter, bool is_v6, const raw_ip& addr, std::vector<hash>& missing_blocks, const bool result)
|
||||
{
|
||||
const uint32_t new_reset_counter = m_resetCounter.load();
|
||||
|
||||
if (!result) {
|
||||
// Client sent bad data, disconnect and ban it
|
||||
if (reset_counter == m_resetCounter.load()) {
|
||||
if (reset_counter == new_reset_counter) {
|
||||
close();
|
||||
LOGWARN(3, "peer " << static_cast<char*>(m_addrString) << " banned for " << DEFAULT_BAN_TIME << " seconds");
|
||||
}
|
||||
@@ -2519,13 +2587,10 @@ void P2PServer::P2PClient::handle_incoming_block(p2pool* pool, PoolBlock& block,
|
||||
server->ban(is_v6, addr, DEFAULT_BAN_TIME);
|
||||
server->remove_peer_from_list(addr);
|
||||
}
|
||||
}
|
||||
|
||||
void P2PServer::P2PClient::post_handle_incoming_block(const PoolBlock& block, const uint32_t reset_counter, std::vector<hash>& missing_blocks)
|
||||
{
|
||||
// We might have been disconnected while side_chain was adding the block
|
||||
// In this case we can't send BLOCK_REQUEST messages on this connection anymore
|
||||
if (reset_counter != m_resetCounter.load()) {
|
||||
if (reset_counter != new_reset_counter) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2540,7 +2605,7 @@ void P2PServer::P2PClient::post_handle_incoming_block(const PoolBlock& block, co
|
||||
P2PClient* c = server->m_fastestPeer;
|
||||
if (c && (c != this) && (c->m_broadcastMaxHeight >= block.m_sidechainHeight)) {
|
||||
LOGINFO(5, "peer " << static_cast<char*>(c->m_addrString) << " is faster, sending BLOCK_REQUEST to it instead");
|
||||
c->post_handle_incoming_block(block, c->m_resetCounter.load(), missing_blocks);
|
||||
c->post_handle_incoming_block(pool, block, c->m_resetCounter.load(), c->m_isV6, c->m_addr, missing_blocks, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2561,7 +2626,7 @@ void P2PServer::P2PClient::post_handle_incoming_block(const PoolBlock& block, co
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool result = server->send(this,
|
||||
const bool send_result = server->send(this,
|
||||
[this, &id](uint8_t* buf, size_t buf_size) -> size_t
|
||||
{
|
||||
LOGINFO(5, "[post_handle_incoming_block] sending BLOCK_REQUEST for id = " << id << " to " << static_cast<char*>(m_addrString));
|
||||
@@ -2580,7 +2645,7 @@ void P2PServer::P2PClient::post_handle_incoming_block(const PoolBlock& block, co
|
||||
return p - buf;
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
if (!send_result) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2591,9 +2656,9 @@ void P2PServer::P2PClient::post_handle_incoming_block(const PoolBlock& block, co
|
||||
const char* P2PServer::P2PClient::software_name() const
|
||||
{
|
||||
switch (m_SoftwareID) {
|
||||
case 0:
|
||||
case SoftwareID::P2Pool:
|
||||
return "P2Pool";
|
||||
case 0x624F6F47UL:
|
||||
case SoftwareID::GoObserver:
|
||||
return "GoObserver";
|
||||
default:
|
||||
return "Unknown";
|
||||
|
||||
+9
-3
@@ -115,8 +115,8 @@ public:
|
||||
void on_block_notify(const uint8_t* buf);
|
||||
|
||||
bool handle_incoming_block_async(const PoolBlock* block, uint64_t max_time_delta = 0);
|
||||
void handle_incoming_block(p2pool* pool, PoolBlock& block, const uint32_t reset_counter, bool is_v6, const raw_ip& addr, std::vector<hash>& missing_blocks);
|
||||
void post_handle_incoming_block(const PoolBlock& block, const uint32_t reset_counter, std::vector<hash>& missing_blocks);
|
||||
void handle_incoming_block(p2pool* pool, PoolBlock& block, std::vector<hash>& missing_blocks, bool& result);
|
||||
void post_handle_incoming_block(p2pool* pool, const PoolBlock& block, const uint32_t reset_counter, bool is_v6, const raw_ip& addr, std::vector<hash>& missing_blocks, const bool result);
|
||||
|
||||
bool is_good() const { return m_handshakeComplete && !m_handshakeInvalid && (m_listenPort >= 0); }
|
||||
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
|
||||
uint32_t m_protocolVersion;
|
||||
uint32_t m_SoftwareVersion;
|
||||
uint32_t m_SoftwareID;
|
||||
SoftwareID m_SoftwareID;
|
||||
|
||||
int64_t m_pingTime;
|
||||
|
||||
@@ -177,6 +177,8 @@ public:
|
||||
|
||||
const PoolBlock* find_block(const hash& id) const;
|
||||
|
||||
void check_for_updates(bool forced = false) const;
|
||||
|
||||
private:
|
||||
const char* get_log_category() const override;
|
||||
|
||||
@@ -226,6 +228,8 @@ private:
|
||||
|
||||
struct Peer
|
||||
{
|
||||
void normalize();
|
||||
|
||||
bool m_isV6;
|
||||
raw_ip m_addr;
|
||||
int m_port;
|
||||
@@ -257,6 +261,7 @@ private:
|
||||
unordered_set<uint64_t> m_blockNotifyRequests;
|
||||
|
||||
P2PClient* m_fastestPeer;
|
||||
std::atomic<bool> m_newP2PoolVersionDetected;
|
||||
|
||||
static void on_broadcast(uv_async_t* handle) { reinterpret_cast<P2PServer*>(handle->data)->on_broadcast(); }
|
||||
void on_broadcast();
|
||||
@@ -267,6 +272,7 @@ private:
|
||||
|
||||
static void on_connect_to_peers(uv_async_t* handle);
|
||||
|
||||
uv_mutex_t m_showPeersLock;
|
||||
uv_async_t m_showPeersAsync;
|
||||
|
||||
static void on_show_peers(uv_async_t* handle) { reinterpret_cast<P2PServer*>(handle->data)->show_peers(); }
|
||||
|
||||
+7
-7
@@ -913,7 +913,7 @@ void p2pool::get_info()
|
||||
[this, host](const char* data, size_t size, double)
|
||||
{
|
||||
if (size > 0) {
|
||||
LOGWARN(1, "get_info RPC request to " << host.m_displayName << " failed: error " << log::const_buf(data, size) << ", trying again in 1 second");
|
||||
LOGWARN(1, "get_info RPC request to host " << 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();
|
||||
@@ -925,7 +925,7 @@ void p2pool::get_info()
|
||||
|
||||
void p2pool::load_found_blocks()
|
||||
{
|
||||
if (!m_api) {
|
||||
if (!m_api || m_stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1107,7 +1107,7 @@ void p2pool::get_miner_data(bool retry)
|
||||
[this, host, retry](const char* data, size_t size, double)
|
||||
{
|
||||
if (size > 0) {
|
||||
LOGWARN(1, "get_miner_data RPC request to " << host.m_displayName << " failed: error " << log::const_buf(data, size) << (retry ? ", trying again in 1 second" : ""));
|
||||
LOGWARN(1, "get_miner_data RPC request to host " << 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;
|
||||
@@ -1277,7 +1277,7 @@ uint32_t p2pool::parse_block_headers_range(const char* data, size_t size)
|
||||
|
||||
void p2pool::api_update_network_stats()
|
||||
{
|
||||
if (!m_api) {
|
||||
if (!m_api || m_stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1308,7 +1308,7 @@ void p2pool::api_update_network_stats()
|
||||
|
||||
void p2pool::api_update_pool_stats()
|
||||
{
|
||||
if (!m_api) {
|
||||
if (!m_api || m_stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1360,7 +1360,7 @@ void p2pool::api_update_pool_stats()
|
||||
|
||||
void p2pool::api_update_stats_mod()
|
||||
{
|
||||
if (!m_api) {
|
||||
if (!m_api || m_stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1453,7 +1453,7 @@ void p2pool::cleanup_mainchain_data(uint64_t height)
|
||||
|
||||
void p2pool::api_update_block_found(const ChainMain* data, const PoolBlock* block)
|
||||
{
|
||||
if (!m_api) {
|
||||
if (!m_api || m_stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+13
-5
@@ -100,14 +100,24 @@ void p2pool_api::create_dir(const std::string& path)
|
||||
|
||||
void p2pool_api::on_stop()
|
||||
{
|
||||
MutexLock lock(m_dumpDataLock);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_dumpToFileAsync), nullptr);
|
||||
}
|
||||
|
||||
void p2pool_api::dump_to_file_async_internal(Category category, const char* filename, Callback<void, log::Stream&>::Base&& callback)
|
||||
{
|
||||
std::vector<char> buf(16384);
|
||||
std::vector<char> buf(1024);
|
||||
log::Stream s(buf.data(), buf.size());
|
||||
callback(s);
|
||||
|
||||
// If the buffer was too small, try again with big enough buffer
|
||||
if (s.m_spilled) {
|
||||
// Assume that the second call will use no more than 2X bytes
|
||||
buf.resize((static_cast<ptrdiff_t>(s.m_pos) + s.m_spilled) * 2 + 1);
|
||||
s.reset(buf.data(), buf.size());
|
||||
callback(s);
|
||||
}
|
||||
|
||||
buf.resize(s.m_pos);
|
||||
|
||||
std::string path;
|
||||
@@ -119,10 +129,8 @@ void p2pool_api::dump_to_file_async_internal(Category category, const char* file
|
||||
case Category::LOCAL: path = m_localPath + filename; break;
|
||||
}
|
||||
|
||||
{
|
||||
MutexLock lock(m_dumpDataLock);
|
||||
m_dumpData[path] = std::move(buf);
|
||||
}
|
||||
MutexLock lock(m_dumpDataLock);
|
||||
m_dumpData[path] = std::move(buf);
|
||||
|
||||
if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(&m_dumpToFileAsync))) {
|
||||
uv_async_send(&m_dumpToFileAsync);
|
||||
|
||||
+2
-5
@@ -396,7 +396,6 @@ RandomX_Hasher_RPC::RandomX_Hasher_RPC(p2pool* pool)
|
||||
GetLoopUserData(&m_loop);
|
||||
|
||||
uv_async_init_checked(&m_loop, &m_shutdownAsync, on_shutdown);
|
||||
uv_async_init_checked(&m_loop, &m_kickTheLoopAsync, nullptr);
|
||||
m_shutdownAsync.data = this;
|
||||
|
||||
uv_mutex_init_checked(&m_requestMutex);
|
||||
@@ -456,8 +455,8 @@ bool RandomX_Hasher_RPC::calculate(const void* data_ptr, size_t size, uint64_t h
|
||||
",\"block_blob\":\"" << log::hex_buf(data, size) << '"' <<
|
||||
",\"seed_hash\":\"\"}}\0";
|
||||
|
||||
volatile int result = 0;
|
||||
volatile bool done = false;
|
||||
std::atomic<int> result{ 0 };
|
||||
std::atomic<bool> done{ false };
|
||||
|
||||
const Params& params = m_pool->params();
|
||||
const Params::Host& host = m_pool->current_host();
|
||||
@@ -485,8 +484,6 @@ bool RandomX_Hasher_RPC::calculate(const void* data_ptr, size_t size, uint64_t h
|
||||
uv_cond_signal(&m_cond);
|
||||
}, &m_loop);
|
||||
|
||||
uv_async_send(&m_kickTheLoopAsync);
|
||||
|
||||
{
|
||||
MutexLock lock2(m_condMutex);
|
||||
while (!done) {
|
||||
|
||||
@@ -115,13 +115,11 @@ private:
|
||||
uv_cond_t m_cond;
|
||||
|
||||
uv_async_t m_shutdownAsync;
|
||||
uv_async_t m_kickTheLoopAsync;
|
||||
|
||||
static void on_shutdown(uv_async_t* async)
|
||||
{
|
||||
RandomX_Hasher_RPC* server = reinterpret_cast<RandomX_Hasher_RPC*>(async->data);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&server->m_shutdownAsync), nullptr);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&server->m_kickTheLoopAsync), nullptr);
|
||||
|
||||
delete GetLoopUserData(&server->m_loop, false);
|
||||
}
|
||||
|
||||
+38
-10
@@ -114,11 +114,11 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name)
|
||||
constexpr char mini_config[] = "mainnet\0" "mini\0" "\0" "10\0" "100000\0" "2160\0" "20\0";
|
||||
|
||||
// Hardcoded default consensus ID
|
||||
if (memcmp(buf, default_config, sizeof(default_config) - 1) == 0) {
|
||||
if ((s.m_pos == sizeof(default_config) - 1) && (memcmp(buf, default_config, sizeof(default_config) - 1) == 0)) {
|
||||
m_consensusId.assign(default_consensus_id, default_consensus_id + HASH_SIZE);
|
||||
}
|
||||
// Hardcoded mini consensus ID
|
||||
else if (memcmp(buf, mini_config, sizeof(mini_config) - 1) == 0) {
|
||||
else if ((s.m_pos == sizeof(mini_config) - 1) && (memcmp(buf, mini_config, sizeof(mini_config) - 1) == 0)) {
|
||||
m_consensusId.assign(mini_consensus_id, mini_consensus_id + HASH_SIZE);
|
||||
}
|
||||
else {
|
||||
@@ -1304,6 +1304,30 @@ bool SideChain::get_difficulty(const PoolBlock* tip, std::vector<DifficultyData>
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SideChain::p2pool_update_available() const
|
||||
{
|
||||
constexpr uint32_t version = (P2POOL_VERSION_MAJOR << 16) | P2POOL_VERSION_MINOR;
|
||||
|
||||
difficulty_type total_p2pool_diff, newer_p2pool_diff;
|
||||
{
|
||||
ReadLock lock(m_sidechainLock);
|
||||
|
||||
const PoolBlock* cur = m_chainTip;
|
||||
|
||||
for (uint64_t i = 0; (i < m_chainWindowSize) && cur; ++i, cur = get_parent(cur)) {
|
||||
if (cur->m_sidechainExtraBuf[0] == static_cast<uint32_t>(SoftwareID::P2Pool)) {
|
||||
total_p2pool_diff += cur->m_difficulty;
|
||||
if (cur->m_sidechainExtraBuf[1] > version) {
|
||||
newer_p2pool_diff += cur->m_difficulty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assume that a new version is out if >= 20% of hashrate is using it already
|
||||
return newer_p2pool_diff * 5 >= total_p2pool_diff;
|
||||
}
|
||||
|
||||
void SideChain::verify_loop(PoolBlock* block)
|
||||
{
|
||||
// PoW is already checked at this point
|
||||
@@ -1544,7 +1568,7 @@ void SideChain::verify(PoolBlock* block)
|
||||
}
|
||||
|
||||
// Check that uncle and parent have the same ancestor (they must be on the same chain)
|
||||
PoolBlock* tmp = parent;
|
||||
const PoolBlock* tmp = parent;
|
||||
while (tmp->m_sidechainHeight > uncle->m_sidechainHeight) {
|
||||
tmp = get_parent(tmp);
|
||||
if (!tmp) {
|
||||
@@ -1567,7 +1591,7 @@ void SideChain::verify(PoolBlock* block)
|
||||
}
|
||||
|
||||
bool same_chain = false;
|
||||
PoolBlock* tmp2 = uncle;
|
||||
const PoolBlock* tmp2 = uncle;
|
||||
for (size_t j = 0; (j < UNCLE_BLOCK_DEPTH) && tmp && tmp2 && (tmp->m_sidechainHeight + UNCLE_BLOCK_DEPTH >= block->m_sidechainHeight); ++j) {
|
||||
if (tmp->m_parent == tmp2->m_parent) {
|
||||
same_chain = true;
|
||||
@@ -2061,21 +2085,20 @@ void SideChain::prune_old_blocks()
|
||||
|
||||
const uint64_t h = tip->m_sidechainHeight - prune_distance;
|
||||
|
||||
uint64_t num_blocks_pruned = 0;
|
||||
std::vector<PoolBlock*> blocks_to_prune;
|
||||
|
||||
for (auto it = m_blocksByHeight.begin(); (it != m_blocksByHeight.end()) && (it->first <= h);) {
|
||||
const uint64_t height = it->first;
|
||||
std::vector<PoolBlock*>& v = it->second;
|
||||
|
||||
v.erase(std::remove_if(v.begin(), v.end(),
|
||||
[this, prune_distance, cur_time, prune_delay, &num_blocks_pruned, height](PoolBlock* block)
|
||||
[this, prune_distance, cur_time, prune_delay, &blocks_to_prune, height](PoolBlock* block)
|
||||
{
|
||||
if ((block->m_depth >= prune_distance) || (cur_time >= block->m_localTimestamp + prune_delay)) {
|
||||
auto it2 = m_blocksById.find(block->m_sidechainId);
|
||||
if (it2 != m_blocksById.end()) {
|
||||
m_blocksById.erase(it2);
|
||||
delete block;
|
||||
++num_blocks_pruned;
|
||||
blocks_to_prune.push_back(block);
|
||||
}
|
||||
else {
|
||||
LOGERR(1, "m_blocksByHeight and m_blocksById are inconsistent at height " << height << ". Fix the code!");
|
||||
@@ -2093,8 +2116,8 @@ void SideChain::prune_old_blocks()
|
||||
}
|
||||
}
|
||||
|
||||
if (num_blocks_pruned) {
|
||||
LOGINFO(4, "pruned " << num_blocks_pruned << " old blocks at heights <= " << h);
|
||||
if (!blocks_to_prune.empty()) {
|
||||
LOGINFO(4, "pruned " << blocks_to_prune.size() << " old blocks at heights <= " << h);
|
||||
|
||||
// If side-chain started pruning blocks it means the initial sync is complete
|
||||
// It's now safe to delete cached blocks
|
||||
@@ -2105,6 +2128,11 @@ void SideChain::prune_old_blocks()
|
||||
// Pre-calc workers are not needed anymore
|
||||
finish_precalc();
|
||||
|
||||
// We can only delete old blocks after the precalc is stopped because it can still use some of them
|
||||
for (const PoolBlock* b : blocks_to_prune) {
|
||||
delete b;
|
||||
}
|
||||
|
||||
#ifdef DEV_TEST_SYNC
|
||||
if (m_firstPruneTime == 0) {
|
||||
m_firstPruneTime = seconds_since_epoch();
|
||||
|
||||
@@ -82,6 +82,8 @@ public:
|
||||
const PoolBlock* chainTip() const { return m_chainTip; }
|
||||
bool precalcFinished() const { return m_precalcFinished.load(); }
|
||||
|
||||
bool p2pool_update_available() const;
|
||||
|
||||
#ifdef P2POOL_UNIT_TESTS
|
||||
difficulty_type m_testMainChainDiff;
|
||||
const unordered_map<hash, PoolBlock*>& blocksById() const { return m_blocksById; }
|
||||
|
||||
+87
-42
@@ -63,6 +63,7 @@ StratumServer::StratumServer(p2pool* pool)
|
||||
m_hashrateData[0] = { seconds_since_epoch(), 0 };
|
||||
|
||||
uv_mutex_init_checked(&m_blobsQueueLock);
|
||||
uv_mutex_init_checked(&m_showWorkersLock);
|
||||
uv_mutex_init_checked(&m_rngLock);
|
||||
uv_rwlock_init_checked(&m_hashrateDataLock);
|
||||
|
||||
@@ -90,7 +91,16 @@ StratumServer::~StratumServer()
|
||||
{
|
||||
shutdown_tcp();
|
||||
|
||||
{
|
||||
MutexLock lock(m_blobsQueueLock);
|
||||
|
||||
for (BlobsData* data : m_blobsQueue) {
|
||||
delete data;
|
||||
}
|
||||
}
|
||||
|
||||
uv_mutex_destroy(&m_blobsQueueLock);
|
||||
uv_mutex_destroy(&m_showWorkersLock);
|
||||
uv_mutex_destroy(&m_rngLock);
|
||||
uv_rwlock_destroy(&m_hashrateDataLock);
|
||||
|
||||
@@ -161,29 +171,19 @@ void StratumServer::on_block(const BlockTemplate& block)
|
||||
|
||||
{
|
||||
MutexLock lock(m_blobsQueueLock);
|
||||
m_blobsQueue.push_back(blobs_data);
|
||||
}
|
||||
|
||||
if (uv_is_closing(reinterpret_cast<uv_handle_t*>(&m_blobsAsync))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int err = uv_async_send(&m_blobsAsync);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_async_send failed, error " << uv_err_name(err));
|
||||
|
||||
bool found = false;
|
||||
{
|
||||
MutexLock lock(m_blobsQueueLock);
|
||||
|
||||
auto it = std::find(m_blobsQueue.begin(), m_blobsQueue.end(), blobs_data);
|
||||
if (it != m_blobsQueue.end()) {
|
||||
found = true;
|
||||
m_blobsQueue.erase(it);
|
||||
}
|
||||
if (uv_is_closing(reinterpret_cast<uv_handle_t*>(&m_blobsAsync))) {
|
||||
delete blobs_data;
|
||||
return;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
m_blobsQueue.push_back(blobs_data);
|
||||
|
||||
const int err = uv_async_send(&m_blobsAsync);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_async_send failed, error " << uv_err_name(err));
|
||||
|
||||
m_blobsQueue.pop_back();
|
||||
delete blobs_data;
|
||||
}
|
||||
}
|
||||
@@ -205,8 +205,8 @@ static bool get_custom_user(const char* s, char (&user)[N])
|
||||
if ((c == '+') || (c == '.')) {
|
||||
break;
|
||||
}
|
||||
// Limit to printable ASCII characters
|
||||
if (c >= ' ' && c <= '~') {
|
||||
// Limit to printable ASCII characters, also skip comma and JSON special characters
|
||||
if (c >= ' ' && c <= '~' && c != ',' && c != '"' && c != '\\') {
|
||||
user[len++] = c;
|
||||
}
|
||||
++s;
|
||||
@@ -246,6 +246,11 @@ static bool get_custom_diff(const char* s, difficulty_type& diff)
|
||||
|
||||
bool StratumServer::on_login(StratumClient* client, uint32_t id, const char* login)
|
||||
{
|
||||
if (client->m_rpcId) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(client->m_addrString) << " tried to login, but it's already logged in");
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint32_t extra_nonce = m_extraNonce.fetch_add(1);
|
||||
|
||||
uint8_t hashing_blob[128];
|
||||
@@ -370,7 +375,7 @@ bool StratumServer::on_submit(StratumClient* client, uint32_t id, const char* jo
|
||||
}
|
||||
|
||||
if (found) {
|
||||
BlockTemplate& block = m_pool->block_template();
|
||||
const BlockTemplate& block = m_pool->block_template();
|
||||
uint64_t height, sidechain_height;
|
||||
difficulty_type mainchain_diff, sidechain_diff;
|
||||
|
||||
@@ -412,6 +417,8 @@ bool StratumServer::on_submit(StratumClient* client, uint32_t id, const char* jo
|
||||
share->m_client = client;
|
||||
share->m_clientIPv6 = client->m_isV6;
|
||||
share->m_clientAddr = client->m_addr;
|
||||
memcpy(share->m_clientAddrString, client->m_addrString, sizeof(share->m_clientAddrString));
|
||||
memcpy(share->m_clientCustomUser, client->m_customUser, sizeof(share->m_clientCustomUser));
|
||||
share->m_clientResetCounter = client->m_resetCounter.load();
|
||||
share->m_rpcId = client->m_rpcId;
|
||||
share->m_id = id;
|
||||
@@ -487,6 +494,8 @@ void StratumServer::print_status()
|
||||
|
||||
void StratumServer::show_workers_async()
|
||||
{
|
||||
MutexLock lock(m_showWorkersLock);
|
||||
|
||||
if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(&m_showWorkersAsync))) {
|
||||
uv_async_send(&m_showWorkersAsync);
|
||||
}
|
||||
@@ -859,7 +868,6 @@ void StratumServer::on_share_found(uv_work_t* req)
|
||||
BACKGROUND_JOB_START(StratumServer::on_share_found);
|
||||
}
|
||||
|
||||
StratumClient* client = share->m_client;
|
||||
p2pool* pool = server->m_pool;
|
||||
|
||||
const uint64_t target = share->m_target;
|
||||
@@ -879,7 +887,7 @@ void StratumServer::on_share_found(uv_work_t* req)
|
||||
|
||||
const uint32_t blob_size = pool->block_template().get_hashing_blob(share->m_templateId, share->m_extraNonce, blob, height, difficulty, sidechain_difficulty, seed_hash, nonce_offset);
|
||||
if (!blob_size) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(client->m_addrString) << " got a stale share");
|
||||
LOGWARN(4, "client " << static_cast<char*>(share->m_clientAddrString) << " got a stale share");
|
||||
share->m_result = SubmittedShare::Result::STALE;
|
||||
return;
|
||||
}
|
||||
@@ -891,13 +899,13 @@ void StratumServer::on_share_found(uv_work_t* req)
|
||||
|
||||
hash pow_hash;
|
||||
if (!pool->calculate_hash(blob, blob_size, height, seed_hash, pow_hash, false)) {
|
||||
LOGWARN(3, "client " << static_cast<char*>(client->m_addrString) << " couldn't check share PoW");
|
||||
LOGWARN(3, "client " << static_cast<char*>(share->m_clientAddrString) << " couldn't check share PoW");
|
||||
share->m_result = SubmittedShare::Result::COULDNT_CHECK_POW;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pow_hash != share->m_resultHash) {
|
||||
LOGWARN(4, "client " << static_cast<char*>(client->m_addrString) << " submitted a share with invalid PoW");
|
||||
LOGWARN(4, "client " << static_cast<char*>(share->m_clientAddrString) << " submitted a share with invalid PoW");
|
||||
share->m_result = SubmittedShare::Result::INVALID_POW;
|
||||
share->m_score = BAD_SHARE_POINTS;
|
||||
|
||||
@@ -944,7 +952,7 @@ void StratumServer::on_share_found(uv_work_t* req)
|
||||
share->m_result = SubmittedShare::Result::OK;
|
||||
}
|
||||
else {
|
||||
LOGWARN(4, "client " << static_cast<char*>(client->m_addrString) << " got a low diff share");
|
||||
LOGWARN(4, "client " << static_cast<char*>(share->m_clientAddrString) << " got a low diff share");
|
||||
share->m_result = SubmittedShare::Result::LOW_DIFF;
|
||||
share->m_score = BAD_SHARE_POINTS;
|
||||
}
|
||||
@@ -953,13 +961,11 @@ void StratumServer::on_share_found(uv_work_t* req)
|
||||
void StratumServer::on_after_share_found(uv_work_t* req, int /*status*/)
|
||||
{
|
||||
SubmittedShare* share = reinterpret_cast<SubmittedShare*>(req->data);
|
||||
StratumClient* client = share->m_client;
|
||||
client->m_score += share->m_score;
|
||||
|
||||
if (share->m_highEnoughDifficulty) {
|
||||
const char* s = client->m_customUser;
|
||||
const char* s = share->m_clientCustomUser;
|
||||
if (share->m_result == SubmittedShare::Result::OK) {
|
||||
LOGINFO(0, log::Green() << "SHARE FOUND: mainchain height " << share->m_mainchainHeight << ", sidechain height " << share->m_sidechainHeight << ", diff " << share->m_sidechainDifficulty << ", client " << static_cast<char*>(client->m_addrString) << (*s ? ", user " : "") << s << ", effort " << share->m_effort << '%');
|
||||
LOGINFO(0, log::Green() << "SHARE FOUND: mainchain height " << share->m_mainchainHeight << ", sidechain height " << share->m_sidechainHeight << ", diff " << share->m_sidechainDifficulty << ", client " << static_cast<char*>(share->m_clientAddrString) << (*s ? ", user " : "") << s << ", effort " << share->m_effort << '%');
|
||||
}
|
||||
else {
|
||||
static const char* reason_list[] = {
|
||||
@@ -973,7 +979,7 @@ void StratumServer::on_after_share_found(uv_work_t* req, int /*status*/)
|
||||
|
||||
const size_t k = static_cast<size_t>(share->m_result);
|
||||
const char* reason = (k < array_size(reason_list)) ? reason_list[k] : "unknown";
|
||||
LOGWARN(0, "INVALID SHARE: mainchain height " << share->m_mainchainHeight << ", sidechain height " << share->m_sidechainHeight << ", diff " << share->m_sidechainDifficulty << ", client " << static_cast<char*>(client->m_addrString) << (*s ? ", user " : "") << s << ", reason: " << reason);
|
||||
LOGWARN(0, "INVALID SHARE: mainchain height " << share->m_mainchainHeight << ", sidechain height " << share->m_sidechainHeight << ", diff " << share->m_sidechainDifficulty << ", client " << static_cast<char*>(share->m_clientAddrString) << (*s ? ", user " : "") << s << ", reason: " << reason);
|
||||
}
|
||||
BACKGROUND_JOB_STOP(StratumServer::on_share_found);
|
||||
}
|
||||
@@ -988,7 +994,9 @@ void StratumServer::on_after_share_found(uv_work_t* req, int /*status*/)
|
||||
|
||||
const bool bad_share = (share->m_result == SubmittedShare::Result::LOW_DIFF) || (share->m_result == SubmittedShare::Result::INVALID_POW);
|
||||
|
||||
if ((client->m_resetCounter.load() == share->m_clientResetCounter) && (client->m_rpcId == share->m_rpcId)) {
|
||||
StratumClient* client = share->m_client;
|
||||
|
||||
if (client->m_resetCounter.load() == share->m_clientResetCounter) {
|
||||
const bool result = server->send(client,
|
||||
[share](uint8_t* buf, size_t buf_size)
|
||||
{
|
||||
@@ -1016,6 +1024,8 @@ void StratumServer::on_after_share_found(uv_work_t* req, int /*status*/)
|
||||
return s.m_pos;
|
||||
});
|
||||
|
||||
client->m_score += share->m_score;
|
||||
|
||||
if (bad_share && (client->m_score <= BAN_THRESHOLD_POINTS)) {
|
||||
client->ban(DEFAULT_BAN_TIME);
|
||||
client->close();
|
||||
@@ -1031,8 +1041,14 @@ void StratumServer::on_after_share_found(uv_work_t* req, int /*status*/)
|
||||
|
||||
void StratumServer::on_shutdown()
|
||||
{
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_blobsAsync), nullptr);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_showWorkersAsync), nullptr);
|
||||
{
|
||||
MutexLock lock(m_blobsQueueLock);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_blobsAsync), nullptr);
|
||||
}
|
||||
{
|
||||
MutexLock lock(m_showWorkersLock);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_showWorkersAsync), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
StratumServer::StratumClient::StratumClient()
|
||||
@@ -1266,7 +1282,7 @@ bool StratumServer::StratumClient::process_submit(rapidjson::Document& doc, uint
|
||||
|
||||
void StratumServer::api_update_local_stats(uint64_t timestamp)
|
||||
{
|
||||
if (!m_pool->api() || !m_pool->params().m_localStats) {
|
||||
if (!m_pool->api() || !m_pool->params().m_localStats || m_pool->stopped()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1329,10 +1345,9 @@ void StratumServer::api_update_local_stats(uint64_t timestamp)
|
||||
|
||||
const double block_reward_share_percent = m_pool->side_chain().get_reward_share(m_pool->params().m_wallet) * 100.0;
|
||||
|
||||
m_pool->api()->set(p2pool_api::Category::LOCAL, "stratum",
|
||||
[hashrate_15m, hashrate_1h, hashrate_24h, total_hashes, shares_found, shares_failed, average_effort, current_effort, connections, incoming_connections, block_reward_share_percent](log::Stream& s)
|
||||
{
|
||||
s << "{\"hashrate_15m\":" << hashrate_15m
|
||||
CallOnLoop(&m_loop, [=]() {
|
||||
m_pool->api()->set(p2pool_api::Category::LOCAL, "stratum", [=](log::Stream& s) {
|
||||
s << "{\"hashrate_15m\":" << hashrate_15m
|
||||
<< ",\"hashrate_1h\":" << hashrate_1h
|
||||
<< ",\"hashrate_24h\":" << hashrate_24h
|
||||
<< ",\"total_hashes\":" << total_hashes
|
||||
@@ -1343,8 +1358,38 @@ void StratumServer::api_update_local_stats(uint64_t timestamp)
|
||||
<< ",\"connections\":" << connections
|
||||
<< ",\"incoming_connections\":" << incoming_connections
|
||||
<< ",\"block_reward_share_percent\":" << block_reward_share_percent
|
||||
<< "}";
|
||||
<< ",\"workers\":[";
|
||||
|
||||
const difficulty_type pool_diff = m_pool->side_chain().difficulty();
|
||||
bool first = true;
|
||||
|
||||
for (const StratumClient* client = static_cast<StratumClient*>(m_connectedClientsList->m_next); client != m_connectedClientsList; client = static_cast<StratumClient*>(client->m_next)) {
|
||||
if (!first) {
|
||||
s << ',';
|
||||
}
|
||||
difficulty_type diff = pool_diff;
|
||||
if (client->m_lastJobTarget > 1) {
|
||||
uint64_t r;
|
||||
diff.lo = udiv128(1, 0, client->m_lastJobTarget, &r);
|
||||
diff.hi = 0;
|
||||
if (r) {
|
||||
++diff.lo;
|
||||
}
|
||||
}
|
||||
|
||||
s << '"' << static_cast<const char*>(client->m_addrString) << ','
|
||||
<< (timestamp - client->m_connectedTime) << ','
|
||||
<< diff << ','
|
||||
<< (client->m_autoDiff.lo / AUTO_DIFF_TARGET_TIME) << ','
|
||||
<< (client->m_rpcId ? client->m_customUser : "not logged in")
|
||||
<< '"';
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
s << "]}";
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace p2pool
|
||||
|
||||
@@ -61,6 +61,7 @@ public:
|
||||
enum {
|
||||
JOBS_SIZE = 4,
|
||||
AUTO_DIFF_SIZE = 64,
|
||||
CUSTOM_USER_SIZE = 32,
|
||||
};
|
||||
|
||||
struct SavedJob {
|
||||
@@ -80,7 +81,7 @@ public:
|
||||
|
||||
difficulty_type m_customDiff;
|
||||
difficulty_type m_autoDiff;
|
||||
char m_customUser[32];
|
||||
char m_customUser[CUSTOM_USER_SIZE];
|
||||
|
||||
uint64_t m_lastJobTarget;
|
||||
|
||||
@@ -127,6 +128,7 @@ private:
|
||||
static void on_blobs_ready(uv_async_t* handle) { reinterpret_cast<StratumServer*>(handle->data)->on_blobs_ready(); }
|
||||
void on_blobs_ready();
|
||||
|
||||
uv_mutex_t m_showWorkersLock;
|
||||
uv_async_t m_showWorkersAsync;
|
||||
|
||||
static void on_show_workers(uv_async_t* handle) { reinterpret_cast<StratumServer*>(handle->data)->show_workers(); }
|
||||
@@ -144,6 +146,8 @@ private:
|
||||
StratumClient* m_client;
|
||||
bool m_clientIPv6;
|
||||
raw_ip m_clientAddr;
|
||||
char m_clientAddrString[Client::ADDR_STRING_SIZE];
|
||||
char m_clientCustomUser[StratumClient::CUSTOM_USER_SIZE];
|
||||
uint32_t m_clientResetCounter;
|
||||
uint32_t m_rpcId;
|
||||
uint32_t m_id;
|
||||
|
||||
+35
-14
@@ -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_loopThreadCreated(false)
|
||||
#ifdef WITH_UPNP
|
||||
, m_portMapping(0)
|
||||
#endif
|
||||
@@ -250,6 +251,8 @@ void TCPServer::start_listening(const std::string& listen_addresses, bool upnp)
|
||||
LOGERR(1, "failed to start event loop thread, error " << uv_err_name(err));
|
||||
PANIC_STOP();
|
||||
}
|
||||
|
||||
m_loopThreadCreated = true;
|
||||
}
|
||||
|
||||
bool TCPServer::connect_to_peer(bool is_v6, const char* ip, int port)
|
||||
@@ -378,7 +381,7 @@ bool TCPServer::connect_to_peer(Client* client)
|
||||
else {
|
||||
sockaddr_in* addr4 = reinterpret_cast<sockaddr_in*>(&addr);
|
||||
addr4->sin_family = AF_INET;
|
||||
memcpy(&addr4->sin_addr, client->m_addr.data + 12, sizeof(in_addr));
|
||||
memcpy(&addr4->sin_addr, client->m_addr.data + sizeof(raw_ip::ipv4_prefix), sizeof(in_addr));
|
||||
addr4->sin_port = htons(static_cast<uint16_t>(client->m_port));
|
||||
}
|
||||
}
|
||||
@@ -392,7 +395,7 @@ bool TCPServer::connect_to_peer(Client* client)
|
||||
else {
|
||||
sockaddr_in* addr4 = reinterpret_cast<sockaddr_in*>(&addr);
|
||||
addr4->sin_family = AF_INET;
|
||||
memcpy(&addr4->sin_addr, m_socks5ProxyIP.data + 12, sizeof(in_addr));
|
||||
memcpy(&addr4->sin_addr, m_socks5ProxyIP.data + sizeof(raw_ip::ipv4_prefix), sizeof(in_addr));
|
||||
addr4->sin_port = htons(static_cast<uint16_t>(m_socks5ProxyPort));
|
||||
}
|
||||
}
|
||||
@@ -416,6 +419,7 @@ void TCPServer::check_event_loop_thread(const char* func) const
|
||||
{
|
||||
if (server_event_loop_thread != this) {
|
||||
LOGERR(1, func << " called from another thread, this is not thread safe");
|
||||
PANIC_STOP();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -473,7 +477,9 @@ void TCPServer::shutdown_tcp()
|
||||
}
|
||||
#endif
|
||||
|
||||
uv_thread_join(&m_loopThread);
|
||||
if (m_loopThreadCreated) {
|
||||
uv_thread_join(&m_loopThread);
|
||||
}
|
||||
|
||||
uv_mutex_destroy(&m_bansLock);
|
||||
|
||||
@@ -592,8 +598,7 @@ void TCPServer::loop(void* data)
|
||||
Client* c = server->m_allocateNewClient();
|
||||
|
||||
ASAN_POISON_MEMORY_REGION(wb, sizeof(WriteBuf));
|
||||
ASAN_POISON_MEMORY_REGION(c, c->size());
|
||||
ASAN_UNPOISON_MEMORY_REGION(&c->m_resetCounter, sizeof(c->m_resetCounter));
|
||||
c->asan_poison_this();
|
||||
|
||||
server->m_writeBuffers.emplace(capacity, wb);
|
||||
server->m_preallocatedClients.emplace_back(c);
|
||||
@@ -777,10 +782,8 @@ void TCPServer::on_new_client(uv_stream_t* server, Client* client)
|
||||
client->m_port = ntohs(reinterpret_cast<sockaddr_in6*>(&peer_addr)->sin6_port);
|
||||
}
|
||||
else {
|
||||
client->m_addr = {};
|
||||
client->m_addr.data[10] = 0xFF;
|
||||
client->m_addr.data[11] = 0xFF;
|
||||
memcpy(client->m_addr.data + 12, &reinterpret_cast<sockaddr_in*>(&peer_addr)->sin_addr, sizeof(in_addr));
|
||||
memcpy(client->m_addr.data, raw_ip::ipv4_prefix, sizeof(raw_ip::ipv4_prefix));
|
||||
memcpy(client->m_addr.data + sizeof(raw_ip::ipv4_prefix), &reinterpret_cast<sockaddr_in*>(&peer_addr)->sin_addr, sizeof(in_addr));
|
||||
client->m_port = ntohs(reinterpret_cast<sockaddr_in*>(&peer_addr)->sin_port);
|
||||
}
|
||||
|
||||
@@ -857,7 +860,12 @@ void TCPServer::on_shutdown(uv_async_t* async)
|
||||
|
||||
uv_timer_init(&s->m_loop, &s->m_shutdownTimer);
|
||||
s->m_shutdownTimer.data = s;
|
||||
|
||||
#ifdef DEV_TEST_SYNC
|
||||
s->m_shutdownCountdown = 300;
|
||||
#else
|
||||
s->m_shutdownCountdown = 30;
|
||||
#endif
|
||||
|
||||
uv_timer_start(&s->m_shutdownTimer,
|
||||
[](uv_timer_t* h)
|
||||
@@ -957,8 +965,7 @@ TCPServer::Client* TCPServer::get_client()
|
||||
|
||||
void TCPServer::return_client(Client* c)
|
||||
{
|
||||
ASAN_POISON_MEMORY_REGION(c, c->size());
|
||||
ASAN_UNPOISON_MEMORY_REGION(&c->m_resetCounter, sizeof(c->m_resetCounter));
|
||||
c->asan_poison_this();
|
||||
m_preallocatedClients.push_back(c);
|
||||
}
|
||||
|
||||
@@ -1100,7 +1107,7 @@ bool TCPServer::Client::on_proxy_handshake(char* data, uint32_t size)
|
||||
}
|
||||
else {
|
||||
buf[3] = 1; // ATYP
|
||||
memcpy(buf + 4, m_addr.data + 12, 4);
|
||||
memcpy(buf + 4, m_addr.data + sizeof(raw_ip::ipv4_prefix), 4);
|
||||
buf[8] = static_cast<uint8_t>(m_port >> 8);
|
||||
buf[9] = static_cast<uint8_t>(m_port & 0xFF);
|
||||
}
|
||||
@@ -1205,9 +1212,10 @@ void TCPServer::Client::close()
|
||||
// Already closed
|
||||
return;
|
||||
}
|
||||
|
||||
m_isClosing = true;
|
||||
|
||||
m_owner->check_event_loop_thread(__func__);
|
||||
|
||||
uv_read_stop(reinterpret_cast<uv_stream_t*>(&m_socket));
|
||||
|
||||
uv_tcp_t* s = &m_socket;
|
||||
@@ -1238,7 +1246,7 @@ void TCPServer::Client::init_addr_string()
|
||||
addr_str = inet_ntop(AF_INET6, m_addr.data, addr_str_buf, sizeof(addr_str_buf));
|
||||
}
|
||||
else {
|
||||
addr_str = inet_ntop(AF_INET, m_addr.data + 12, addr_str_buf, sizeof(addr_str_buf));
|
||||
addr_str = inet_ntop(AF_INET, m_addr.data + sizeof(raw_ip::ipv4_prefix), addr_str_buf, sizeof(addr_str_buf));
|
||||
}
|
||||
|
||||
if (addr_str) {
|
||||
@@ -1257,4 +1265,17 @@ void TCPServer::Client::init_addr_string()
|
||||
}
|
||||
}
|
||||
|
||||
void TCPServer::Client::asan_poison_this() const
|
||||
{
|
||||
#ifdef P2POOL_ASAN
|
||||
const uint8_t* begin = reinterpret_cast<const uint8_t*>(this);
|
||||
const uint8_t* counter_begin = reinterpret_cast<const uint8_t*>(&m_resetCounter);
|
||||
const uint8_t* counter_end = counter_begin + sizeof(m_resetCounter);
|
||||
const uint8_t* end = begin + size();
|
||||
|
||||
ASAN_POISON_MEMORY_REGION(begin, counter_begin - begin);
|
||||
ASAN_POISON_MEMORY_REGION(counter_end, end - counter_end);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace p2pool
|
||||
|
||||
+8
-1
@@ -70,6 +70,8 @@ public:
|
||||
|
||||
void init_addr_string();
|
||||
|
||||
void asan_poison_this() const;
|
||||
|
||||
char* m_readBuf;
|
||||
uint32_t m_readBufSize;
|
||||
|
||||
@@ -87,9 +89,13 @@ public:
|
||||
bool m_isClosing;
|
||||
uint32_t m_numRead;
|
||||
|
||||
enum {
|
||||
ADDR_STRING_SIZE = 72,
|
||||
};
|
||||
|
||||
raw_ip m_addr;
|
||||
int m_port;
|
||||
char m_addrString[72];
|
||||
char m_addrString[ADDR_STRING_SIZE];
|
||||
|
||||
enum class Socks5ProxyState {
|
||||
Default,
|
||||
@@ -149,6 +155,7 @@ protected:
|
||||
int m_defaultBacklog;
|
||||
|
||||
uv_thread_t m_loopThread;
|
||||
std::atomic<bool> m_loopThreadCreated;
|
||||
|
||||
static void loop(void* data);
|
||||
|
||||
|
||||
+50
-21
@@ -44,7 +44,13 @@ LOG_CATEGORY(Util)
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
const char* VERSION = "v" STR2(P2POOL_VERSION_MAJOR) "." STR2(P2POOL_VERSION_MINOR) " (built"
|
||||
#if defined(P2POOL_VERSION_PATCH) && (P2POOL_VERSION_PATCH > 0)
|
||||
#define P2POOL_VERSION_PATCH_STR "." STR2(P2POOL_VERSION_PATCH)
|
||||
#else
|
||||
#define P2POOL_VERSION_PATCH_STR ""
|
||||
#endif
|
||||
|
||||
const char* VERSION = "v" STR2(P2POOL_VERSION_MAJOR) "." STR2(P2POOL_VERSION_MINOR) P2POOL_VERSION_PATCH_STR " (built"
|
||||
#if defined(__clang__)
|
||||
" with clang/" __clang_version__
|
||||
#elif defined(__GNUC__)
|
||||
@@ -54,6 +60,20 @@ const char* VERSION = "v" STR2(P2POOL_VERSION_MAJOR) "." STR2(P2POOL_VERSION_MIN
|
||||
#endif
|
||||
" on " __DATE__ ")";
|
||||
|
||||
SoftwareID get_software_id(uint32_t value)
|
||||
{
|
||||
switch (value) {
|
||||
case static_cast<uint32_t>(SoftwareID::P2Pool):
|
||||
return SoftwareID::P2Pool;
|
||||
|
||||
case static_cast<uint32_t>(SoftwareID::GoObserver):
|
||||
return SoftwareID::GoObserver;
|
||||
|
||||
default:
|
||||
return SoftwareID::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
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 };
|
||||
|
||||
@@ -323,9 +343,13 @@ struct BackgroundJobTracker::Impl
|
||||
{
|
||||
MutexLock lock(m_lock);
|
||||
|
||||
auto it = m_jobs.insert({ name, 1 });
|
||||
auto it = m_jobs.emplace(name, 1);
|
||||
if (!it.second) {
|
||||
++it.first->second;
|
||||
const int32_t n = ++it.first->second;
|
||||
// Print the warning only once as the number goes past 20
|
||||
if (n == 20) {
|
||||
LOGWARN(3, "Performance warning: there are " << n << " instances of " << name << " running in the background. This shouldn't be normally happening - check logs for other warnings and errors.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,8 +363,8 @@ struct BackgroundJobTracker::Impl
|
||||
return;
|
||||
}
|
||||
|
||||
--it->second;
|
||||
if (it->second <= 0) {
|
||||
const int32_t n = --it->second;
|
||||
if (n <= 0) {
|
||||
m_jobs.erase(it);
|
||||
}
|
||||
}
|
||||
@@ -484,22 +508,29 @@ bool get_dns_txt_records_base(const std::string& host, Callback<void, const char
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
PDNS_RECORD pQueryResults;
|
||||
if (DnsQuery(host.c_str(), DNS_TYPE_TEXT, DNS_QUERY_STANDARD, NULL, &pQueryResults, NULL) != 0) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
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);
|
||||
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];
|
||||
if (s) {
|
||||
const size_t n = strlen(s);
|
||||
if (n > 0) {
|
||||
callback(s, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DnsRecordListFree(pQueryResults, DnsFreeRecordList);
|
||||
DnsRecordListFree(pQueryResults, DnsFreeRecordList);
|
||||
}
|
||||
catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#elif defined(HAVE_RES_QUERY)
|
||||
@@ -602,10 +633,8 @@ bool str_to_ip(bool is_v6, const char* ip, raw_ip& result)
|
||||
LOGERR(1, "failed to parse IPv4 address " << ip << ", error " << uv_err_name(err));
|
||||
return false;
|
||||
}
|
||||
result = {};
|
||||
result.data[10] = 0xFF;
|
||||
result.data[11] = 0xFF;
|
||||
memcpy(result.data + 12, &addr4->sin_addr, sizeof(in_addr));
|
||||
memcpy(result.data, raw_ip::ipv4_prefix, sizeof(raw_ip::ipv4_prefix));
|
||||
memcpy(result.data + sizeof(raw_ip::ipv4_prefix), &addr4->sin_addr, sizeof(in_addr));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
+18
-3
@@ -35,10 +35,19 @@
|
||||
namespace p2pool {
|
||||
|
||||
#define P2POOL_VERSION_MAJOR 3
|
||||
#define P2POOL_VERSION_MINOR 6
|
||||
#define P2POOL_VERSION_MINOR 9
|
||||
#define P2POOL_VERSION_PATCH 0
|
||||
|
||||
extern const char* VERSION;
|
||||
|
||||
enum class SoftwareID : uint32_t {
|
||||
P2Pool = 0,
|
||||
GoObserver = 0x624F6F47UL,
|
||||
Unknown = 0xFFFFFFFFUL,
|
||||
};
|
||||
|
||||
SoftwareID get_software_id(uint32_t value);
|
||||
|
||||
template<typename T> struct not_implemented { enum { value = 0 }; };
|
||||
|
||||
struct nocopy_nomove
|
||||
@@ -90,11 +99,17 @@ static FORCEINLINE bool from_hex(char c, T& out_value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T, bool is_signed> struct is_negative_helper {};
|
||||
template<typename T> struct is_negative_helper<T, false> { static FORCEINLINE bool value(T) { return false; } };
|
||||
template<typename T> struct is_negative_helper<T, true> { static FORCEINLINE bool value(T x) { return (x < 0); } };
|
||||
|
||||
template<typename T> FORCEINLINE bool is_negative(T x) { return is_negative_helper<T, std::is_signed<T>::value>::value(x); }
|
||||
|
||||
template<typename T, bool is_signed> struct abs_helper {};
|
||||
template<typename T> struct abs_helper<T, false> { static FORCEINLINE T value(T x) { return x; } };
|
||||
template<typename T> struct abs_helper<T, true> { static FORCEINLINE T value(T x) { return (x >= 0) ? x : -x; } };
|
||||
template<typename T> struct abs_helper<T, true> { static FORCEINLINE std::make_unsigned_t<T> value(T x) { return (x < 0) ? -x : x; } };
|
||||
|
||||
template<typename T> FORCEINLINE T abs(T x) { return abs_helper<T, std::is_signed<T>::value>::value(x); }
|
||||
template<typename T> FORCEINLINE std::make_unsigned_t<T> abs(T x) { return abs_helper<T, std::is_signed<T>::value>::value(x); }
|
||||
|
||||
template<typename T, typename U>
|
||||
FORCEINLINE void writeVarint(T value, U&& callback)
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ ZMQReader::ZMQReader(const std::string& address, uint32_t zmq_port, const std::s
|
||||
break;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
LOGWARN(1, "failed to to bind port " << i << " for ZMQ publisher, error " << e.what());
|
||||
LOGWARN(1, "failed to to bind port " << port << " for ZMQ publisher, error " << e.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ set(SOURCES
|
||||
src/difficulty_type_tests.cpp
|
||||
src/hash_tests.cpp
|
||||
src/keccak_tests.cpp
|
||||
src/log_tests.cpp
|
||||
src/main.cpp
|
||||
src/pool_block_tests.cpp
|
||||
src/util_tests.cpp
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -0,0 +1,281 @@
|
||||
# This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
# Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
|
||||
allowedAPIs = {
|
||||
"getaddrinfo",
|
||||
"freeaddrinfo",
|
||||
"WSAPoll",
|
||||
"WSACreateEvent",
|
||||
"WSACloseEvent",
|
||||
"WSARecvFrom",
|
||||
"WSASend",
|
||||
"WSARecv",
|
||||
"WSADuplicateSocketW",
|
||||
"WSASocketW",
|
||||
"WSAIoctl",
|
||||
"getnameinfo",
|
||||
"WSASocketA",
|
||||
"GetAdaptersAddresses",
|
||||
"GetBestInterface",
|
||||
"DnsFree",
|
||||
"LoadLibraryExW",
|
||||
"RtlPcToFileHeader",
|
||||
"RtlUnwindEx",
|
||||
"GetCPInfo",
|
||||
"GetStringTypeW",
|
||||
"GetDriveTypeW",
|
||||
"DecodePointer",
|
||||
"EncodePointer",
|
||||
"FreeLibraryAndExitThread",
|
||||
"SystemTimeToTzSpecificLocalTime",
|
||||
"CreateThread",
|
||||
"LCMapStringEx",
|
||||
"ExitThread",
|
||||
"GetModuleHandleExW",
|
||||
"SetStdHandle",
|
||||
"FlsFree",
|
||||
"FlsSetValue",
|
||||
"FlsGetValue",
|
||||
"SetFilePointer",
|
||||
"SetEndOfFile",
|
||||
"UnmapViewOfFile",
|
||||
"GetLastError",
|
||||
"FlushViewOfFile",
|
||||
"CreateFileA",
|
||||
"CloseHandle",
|
||||
"CreateFileMappingA",
|
||||
"MapViewOfFile",
|
||||
"FlushFileBuffers",
|
||||
"GetStdHandle",
|
||||
"WriteConsoleA",
|
||||
"SetConsoleMode",
|
||||
"GetConsoleMode",
|
||||
"FormatMessageA",
|
||||
"SetThreadPriority",
|
||||
"GetCurrentThread",
|
||||
"SetThreadPriorityBoost",
|
||||
"IsDebuggerPresent",
|
||||
"Sleep",
|
||||
"RaiseException",
|
||||
"InitializeCriticalSection",
|
||||
"EnterCriticalSection",
|
||||
"LeaveCriticalSection",
|
||||
"DeleteCriticalSection",
|
||||
"QueryPerformanceCounter",
|
||||
"QueryPerformanceFrequency",
|
||||
"GetTickCount",
|
||||
"FreeLibrary",
|
||||
"GetProcAddress",
|
||||
"LoadLibraryA",
|
||||
"SetHandleInformation",
|
||||
"WaitForSingleObject",
|
||||
"GetCurrentThreadId",
|
||||
"TryEnterCriticalSection",
|
||||
"GetCurrentProcessId",
|
||||
"GetHandleInformation",
|
||||
"SetLastError",
|
||||
"CreateIoCompletionPort",
|
||||
"GetQueuedCompletionStatusEx",
|
||||
"InitializeSRWLock",
|
||||
"ReleaseSRWLockExclusive",
|
||||
"ReleaseSRWLockShared",
|
||||
"AcquireSRWLockExclusive",
|
||||
"AcquireSRWLockShared",
|
||||
"InitOnceExecuteOnce",
|
||||
"GetTickCount64",
|
||||
"GetModuleHandleW",
|
||||
"SetFileCompletionNotificationModes",
|
||||
"WideCharToMultiByte",
|
||||
"DuplicateHandle",
|
||||
"TryAcquireSRWLockShared",
|
||||
"InitializeConditionVariable",
|
||||
"WakeConditionVariable",
|
||||
"WakeAllConditionVariable",
|
||||
"SleepConditionVariableCS",
|
||||
"SetEvent",
|
||||
"ReleaseSemaphore",
|
||||
"CreateEventA",
|
||||
"GetCurrentProcess",
|
||||
"ResumeThread",
|
||||
"TlsAlloc",
|
||||
"TlsGetValue",
|
||||
"TlsSetValue",
|
||||
"TlsFree",
|
||||
"GetNativeSystemInfo",
|
||||
"CreateSemaphoreA",
|
||||
"GetFileType",
|
||||
"PostQueuedCompletionStatus",
|
||||
"CreateFileW",
|
||||
"ResetEvent",
|
||||
"QueueUserWorkItem",
|
||||
"GetFileAttributesExW",
|
||||
"UnregisterWait",
|
||||
"GetNumberOfConsoleInputEvents",
|
||||
"ReadConsoleInputW",
|
||||
"ReadConsoleW",
|
||||
"WriteConsoleW",
|
||||
"FillConsoleOutputCharacterW",
|
||||
"FillConsoleOutputAttribute",
|
||||
"GetConsoleCursorInfo",
|
||||
"SetConsoleCursorInfo",
|
||||
"GetConsoleScreenBufferInfo",
|
||||
"SetConsoleCursorPosition",
|
||||
"SetConsoleTextAttribute",
|
||||
"WriteConsoleInputW",
|
||||
"ReadFile",
|
||||
"WriteFile",
|
||||
"ConnectNamedPipe",
|
||||
"SetNamedPipeHandleState",
|
||||
"PeekNamedPipe",
|
||||
"CreateNamedPipeW",
|
||||
"CancelIoEx",
|
||||
"CancelSynchronousIo",
|
||||
"SwitchToThread",
|
||||
"LocalFree",
|
||||
"GetNamedPipeHandleStateA",
|
||||
"GetNamedPipeClientProcessId",
|
||||
"GetNamedPipeServerProcessId",
|
||||
"MultiByteToWideChar",
|
||||
"SetConsoleCtrlHandler",
|
||||
"SetErrorMode",
|
||||
"GetQueuedCompletionStatus",
|
||||
"CreateDirectoryW",
|
||||
"FindClose",
|
||||
"FindFirstFileW",
|
||||
"FindNextFileW",
|
||||
"RtlUnwind",
|
||||
"GetFileAttributesW",
|
||||
"GetFileInformationByHandle",
|
||||
"GetFileSizeEx",
|
||||
"GetFinalPathNameByHandleW",
|
||||
"GetFullPathNameW",
|
||||
"RemoveDirectoryW",
|
||||
"SetFilePointerEx",
|
||||
"SetFileTime",
|
||||
"DeviceIoControl",
|
||||
"GetSystemInfo",
|
||||
"GetSystemTimeAsFileTime",
|
||||
"ReOpenFile",
|
||||
"CopyFileW",
|
||||
"MoveFileExW",
|
||||
"CreateHardLinkW",
|
||||
"GetFileInformationByHandleEx",
|
||||
"CreateSymbolicLinkW",
|
||||
"CancelIo",
|
||||
"DebugBreak",
|
||||
"GetCurrentDirectoryW",
|
||||
"TerminateProcess",
|
||||
"GetExitCodeProcess",
|
||||
"UnregisterWaitEx",
|
||||
"LCMapStringW",
|
||||
"GetLongPathNameW",
|
||||
"ReadDirectoryChangesW",
|
||||
"GetEnvironmentStringsW",
|
||||
"FreeEnvironmentStringsW",
|
||||
"SetEnvironmentVariableW",
|
||||
"GetModuleFileNameW",
|
||||
"FileTimeToSystemTime",
|
||||
"GetModuleHandleA",
|
||||
"LoadLibraryExA",
|
||||
"GetStartupInfoW",
|
||||
"FormatMessageW",
|
||||
"InitializeCriticalSectionEx",
|
||||
"GetSystemDirectoryA",
|
||||
"WaitForSingleObjectEx",
|
||||
"GetEnvironmentVariableA",
|
||||
"SleepEx",
|
||||
"VerSetConditionMask",
|
||||
"VerifyVersionInfoW",
|
||||
"VirtualProtect",
|
||||
"VirtualFree",
|
||||
"VirtualAlloc",
|
||||
"GetLargePageMinimum",
|
||||
"HeapFree",
|
||||
"HeapAlloc",
|
||||
"GetProcessHeap",
|
||||
"FlsAlloc",
|
||||
"SleepConditionVariableSRW",
|
||||
"GetExitCodeThread",
|
||||
"InitializeSListHead",
|
||||
"CreateEventW",
|
||||
"InitializeCriticalSectionAndSpinCount",
|
||||
"IsProcessorFeaturePresent",
|
||||
"SetUnhandledExceptionFilter",
|
||||
"UnhandledExceptionFilter",
|
||||
"RtlVirtualUnwind",
|
||||
"RtlLookupFunctionEntry",
|
||||
"SetFileAttributesW",
|
||||
"GetConsoleOutputCP",
|
||||
"ExitProcess",
|
||||
"GetCommandLineA",
|
||||
"GetCommandLineW",
|
||||
"GetDateFormatW",
|
||||
"GetTimeFormatW",
|
||||
"CompareStringW",
|
||||
"GetLocaleInfoW",
|
||||
"IsValidLocale",
|
||||
"GetUserDefaultLCID",
|
||||
"EnumSystemLocalesW",
|
||||
"HeapReAlloc",
|
||||
"HeapSize",
|
||||
"FindFirstFileExW",
|
||||
"IsValidCodePage",
|
||||
"GetACP",
|
||||
"GetOEMCP",
|
||||
"GetTimeZoneInformation",
|
||||
"RegisterWaitForSingleObject",
|
||||
"GetDiskFreeSpaceW",
|
||||
"RtlCaptureContext",
|
||||
"GetMessageA",
|
||||
"GetSystemMetrics",
|
||||
"MapVirtualKeyW",
|
||||
"DispatchMessageA",
|
||||
"TranslateMessage",
|
||||
"AdjustTokenPrivileges",
|
||||
"LookupPrivilegeValueA",
|
||||
"CryptDestroyHash",
|
||||
"CryptHashData",
|
||||
"CryptCreateHash",
|
||||
"CryptGetHashParam",
|
||||
"CryptReleaseContext",
|
||||
"CryptAcquireContextA",
|
||||
"SystemFunction036",
|
||||
"OpenProcessToken",
|
||||
"SetSecurityDescriptorDacl",
|
||||
"InitializeSecurityDescriptor",
|
||||
"BCryptGenRandom",
|
||||
"GetConsoleCP",
|
||||
}
|
||||
|
||||
f = open(sys.argv[1], 'r')
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
|
||||
exit_code = 0
|
||||
count = 0
|
||||
|
||||
for line in lines:
|
||||
count += 1
|
||||
api = line[29:].strip()
|
||||
if api not in allowedAPIs:
|
||||
print('API call "{}" is not checked for Windows 7 compatibility. Check it and then add it to the list in tests/src/check_imports.py'.format(api))
|
||||
exit_code = 1
|
||||
|
||||
if exit_code == 0:
|
||||
print('{} imports checked successfully'.format(count))
|
||||
|
||||
sys.exit(exit_code)
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
TEST(log, stream)
|
||||
{
|
||||
constexpr int N = 63;
|
||||
|
||||
char buf[N + 1] = {};
|
||||
log::Stream s(buf);
|
||||
|
||||
for (int iter = 0; iter < 2; ++iter) {
|
||||
ASSERT_EQ(s.m_bufSize, N);
|
||||
|
||||
for (int i = 0; i < N; ++i) {
|
||||
s << ' ';
|
||||
|
||||
ASSERT_EQ(s.m_pos, i + 1);
|
||||
ASSERT_EQ(s.m_spilled, 0);
|
||||
}
|
||||
|
||||
s << ' ';
|
||||
|
||||
ASSERT_EQ(s.m_pos, N);
|
||||
ASSERT_EQ(s.m_spilled, 1);
|
||||
|
||||
for (int i = 0; i < N; ++i) {
|
||||
ASSERT_EQ(buf[i], ' ');
|
||||
}
|
||||
|
||||
ASSERT_EQ(buf[N], '\0');
|
||||
|
||||
s.reset(buf, N + 1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(log, pad_right)
|
||||
{
|
||||
constexpr int N = 63;
|
||||
|
||||
char buf[N + 1] = {};
|
||||
log::Stream s(buf);
|
||||
|
||||
s << log::pad_right('1', N);
|
||||
|
||||
ASSERT_EQ(s.m_pos, N);
|
||||
ASSERT_EQ(s.m_spilled, 0);
|
||||
|
||||
ASSERT_EQ(buf[0], '1');
|
||||
|
||||
for (int i = 1; i < N; ++i) {
|
||||
ASSERT_EQ(buf[i], ' ');
|
||||
}
|
||||
|
||||
ASSERT_EQ(buf[N], '\0');
|
||||
}
|
||||
|
||||
template<typename T, bool hex>
|
||||
void check_number(T value)
|
||||
{
|
||||
constexpr size_t N = 64;
|
||||
|
||||
char buf[N];
|
||||
memset(buf, -1, N);
|
||||
log::Stream s(buf);
|
||||
s << log::BasedValue<T, hex ? 16 : 10>(value) << '\0';
|
||||
|
||||
char buf2[N];
|
||||
memset(buf2, -1, N);
|
||||
snprintf(buf2, N, hex ? "%llx" : (std::is_signed<T>::value ? "%lld" : "%llu"), value);
|
||||
|
||||
ASSERT_EQ(memcmp(buf, buf2, N), 0);
|
||||
}
|
||||
|
||||
TEST(log, numbers)
|
||||
{
|
||||
for (int64_t i = -1024; i <= 1024; ++i) {
|
||||
check_number<int64_t, false>(i);
|
||||
|
||||
if (i >= 0) {
|
||||
check_number<int64_t, true>(i);
|
||||
check_number<uint64_t, false>(i);
|
||||
check_number<uint64_t, true>(i);
|
||||
}
|
||||
}
|
||||
|
||||
check_number<int64_t, false>(std::numeric_limits<int64_t>::min());
|
||||
check_number<int64_t, false>(std::numeric_limits<int64_t>::max());
|
||||
check_number<int64_t, true>(std::numeric_limits<int64_t>::max());
|
||||
|
||||
check_number<uint64_t, false>(std::numeric_limits<uint64_t>::max());
|
||||
check_number<uint64_t, true>(std::numeric_limits<uint64_t>::max());
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
# This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
# Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import socket
|
||||
import time
|
||||
import sys
|
||||
@@ -5,19 +20,26 @@ import json
|
||||
|
||||
f = open('stratum_dummy' + sys.argv[1] + '.log', 'wb')
|
||||
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.settimeout(1)
|
||||
sock.setblocking(True)
|
||||
|
||||
f.write(b'Connecting')
|
||||
time.sleep(5)
|
||||
f.flush()
|
||||
|
||||
while True:
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.settimeout(1)
|
||||
sock.setblocking(True)
|
||||
|
||||
if sock.connect_ex(('127.0.0.1', 3333)) == 0:
|
||||
break;
|
||||
|
||||
sock.close()
|
||||
|
||||
while sock.connect_ex(('127.0.0.1', 3333)) != 0:
|
||||
f.write(b'.')
|
||||
f.flush()
|
||||
print('.')
|
||||
time.sleep(1)
|
||||
|
||||
f.write(b'\n')
|
||||
f.flush()
|
||||
|
||||
diff = ''
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
race:p2pool::log::Worker::run()
|
||||
race:p2pool::log::Worker::write
|
||||
called_from_lib:libzmq.so
|
||||
race_top:do_loglevel
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021-2022 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of the Monero P2Pool <https://github.com/SChernykh/p2pool>
|
||||
* Copyright (c) 2021 SChernykh <https://github.com/SChernykh>
|
||||
* Copyright (c) 2021-2023 SChernykh <https://github.com/SChernykh>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
Reference in New Issue
Block a user