Compare commits
123 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 | |||
| fecfa18999 | |||
| d8b23cd13c | |||
| 0e0101f507 | |||
| 17a17850ea | |||
| 71d4a6dab0 | |||
| 936d3b5280 | |||
| fac9c23103 | |||
| 3674401923 | |||
| 66d6d0dc33 | |||
| 31ce134413 | |||
| b8e6aae289 | |||
| 8f620712ef | |||
| 1069d1c066 | |||
| bc0634a541 | |||
| 8d65a99fe4 | |||
| 6e68714c26 | |||
| 06ff7b661a | |||
| 70a6442b46 | |||
| 9e7d394ae7 | |||
| 326b2d7a04 | |||
| f3045a5e80 | |||
| b3d72cbfcb | |||
| 76c4573c39 | |||
| 741bec9874 | |||
| 46aed06523 | |||
| 7630c1a883 | |||
| 2877e5dfc1 | |||
| 05b88a48a3 | |||
| c74b567fe4 | |||
| a6b6cb0f09 | |||
| 86e9af6fd7 | |||
| 8776f7dfbb | |||
| 929f908a86 | |||
| 229d7b052a | |||
| a5896f7ae8 | |||
| 114c2cee93 | |||
| 7f413ec994 | |||
| bd30a68e7d | |||
| f4a18726b5 | |||
| 50e284357c | |||
| 2ddb03e2be | |||
| ebae616138 | |||
| 0f88640575 | |||
| 75cc82ae0c | |||
| 32dc235aa5 | |||
| 6ffe1d81c2 | |||
| 5b245e64d3 | |||
| a067361d74 | |||
| a7f66c8883 | |||
| e03e7d831e | |||
| 1219ed0dd6 | |||
| fe2ff95f19 | |||
| d72f0ce40c | |||
| df43e2c126 | |||
| d8ecc1174d | |||
| 3e269b49d4 | |||
| 72c9f3b0db | |||
| 2f5b0db786 | |||
| 8d9f16c387 | |||
| d6cb0ee8a0 | |||
| 5444701c38 | |||
| 396479c2bf |
+221
-65
@@ -1,8 +1,110 @@
|
||||
name: C/C++ CI
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
- 'README.md'
|
||||
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build-alpine-static:
|
||||
|
||||
timeout-minutes: 75
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {arch: x86_64, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline"}
|
||||
- {arch: aarch64, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline -mfix-cortex-a53-835769 -mfix-cortex-a53-843419"}
|
||||
|
||||
steps:
|
||||
- name: Setup Alpine Linux
|
||||
uses: jirutka/setup-alpine@v1
|
||||
with:
|
||||
arch: ${{ matrix.config.arch }}
|
||||
|
||||
- name: Install dependencies
|
||||
shell: alpine.sh --root {0}
|
||||
run: |
|
||||
apk add git cmake gcc g++ make
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Build libcurl
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_FLAGS="-Os ${{ matrix.config.flags }}" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j$(nproc)
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
- name: Build libuv
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build libzmq
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DCMAKE_CXX_FLAGS='-Os ${{ matrix.config.flags }}' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build p2pool
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_BINARY=ON -DARCH_ID=${{ matrix.config.arch }}
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run RandomX tests
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
build/p2pool --test
|
||||
build/external/src/RandomX/randomx-tests
|
||||
|
||||
- name: Build tests
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
cd tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON -DARCH_ID=${{ matrix.config.arch }}
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run tests
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
cd tests/build
|
||||
gunzip *.gz
|
||||
./p2pool_tests
|
||||
|
||||
- name: List directory
|
||||
run: |
|
||||
cd build
|
||||
ls -la
|
||||
file p2pool
|
||||
|
||||
- name: Archive binary
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool-alpine-static-${{ matrix.config.arch }}
|
||||
path: build/p2pool
|
||||
|
||||
build-ubuntu:
|
||||
|
||||
timeout-minutes: 10
|
||||
@@ -30,15 +132,20 @@ jobs:
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }}
|
||||
cmake .. -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }} -DCMAKE_C_FLAGS='-flto=2' -DCMAKE_CXX_FLAGS='-flto=2'
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run RandomX tests
|
||||
run: |
|
||||
build/p2pool --test
|
||||
build/external/src/RandomX/randomx-tests
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }}
|
||||
cmake .. -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }} -DCMAKE_C_FLAGS='-flto=2' -DCMAKE_CXX_FLAGS='-flto=2'
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run tests
|
||||
@@ -58,6 +165,11 @@ jobs:
|
||||
timeout-minutes: 15
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=inline"}
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
@@ -74,7 +186,7 @@ jobs:
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_FLAGS="-Os" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
cmake . -DCMAKE_C_FLAGS="-Os ${{ matrix.config.flags }}" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j$(nproc)
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
@@ -83,7 +195,7 @@ jobs:
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os' -DBUILD_TESTING=OFF
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build libzmq
|
||||
@@ -91,22 +203,27 @@ jobs:
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os' -DCMAKE_CXX_FLAGS='-Os' -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DWITH_PERF_TOOL=OFF
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DCMAKE_CXX_FLAGS='-Os ${{ matrix.config.flags }}' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DSTATIC_LIBS=ON
|
||||
cmake .. -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run RandomX tests
|
||||
run: |
|
||||
build/p2pool --test
|
||||
build/external/src/RandomX/randomx-tests
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DSTATIC_LIBS=ON
|
||||
cmake .. -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run tests
|
||||
@@ -123,20 +240,20 @@ jobs:
|
||||
|
||||
build-ubuntu-aarch64:
|
||||
|
||||
timeout-minutes: 10
|
||||
timeout-minutes: 15
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {os: ubuntu-20.04}
|
||||
- {os: ubuntu-22.04}
|
||||
- {os: ubuntu-20.04, flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -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
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y git build-essential cmake gcc-aarch64-linux-gnu g++-aarch64-linux-gnu binutils-aarch64-linux-gnu
|
||||
sudo apt install -y git build-essential cmake gcc-aarch64-linux-gnu g++-aarch64-linux-gnu binutils-aarch64-linux-gnu qemu-user
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
@@ -146,7 +263,7 @@ jobs:
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_C_FLAGS="-Os" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
cmake . -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_C_FLAGS="-Os ${{ matrix.config.flags }}" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j$(nproc)
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
@@ -155,7 +272,7 @@ jobs:
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_C_FLAGS='-Os' -DBUILD_TESTING=OFF
|
||||
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build libzmq
|
||||
@@ -163,16 +280,35 @@ jobs:
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_C_FLAGS='-Os' -DCMAKE_CXX_FLAGS='-Os' -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DWITH_PERF_TOOL=OFF
|
||||
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DCMAKE_CXX_FLAGS='-Os ${{ matrix.config.flags }}' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_STRIP=/usr/bin/aarch64-linux-gnu-strip -DSTATIC_LIBS=ON -DARCH_ID=aarch64
|
||||
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_STRIP=/usr/bin/aarch64-linux-gnu-strip -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON -DARCH_ID=aarch64
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run RandomX tests
|
||||
run: |
|
||||
qemu-aarch64 -L /usr/aarch64-linux-gnu build/p2pool --test
|
||||
qemu-aarch64 -L /usr/aarch64-linux-gnu build/external/src/RandomX/randomx-tests
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=aarch64-linux-gnu-gcc -DCMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ -DCMAKE_STRIP=/usr/bin/aarch64-linux-gnu-strip -DCMAKE_C_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections' -DSTATIC_LIBS=ON -DARCH_ID=aarch64
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd tests/build
|
||||
gunzip *.gz
|
||||
qemu-aarch64 -L /usr/aarch64-linux-gnu ./p2pool_tests
|
||||
|
||||
- name: Archive binary
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -184,6 +320,12 @@ jobs:
|
||||
timeout-minutes: 45
|
||||
runs-on: windows-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {c: "gcc", cxx: "g++", flags: "-flto=2 -fuse-linker-plugin -ffunction-sections -Wno-error=maybe-uninitialized -Wno-error=attributes"}
|
||||
- {c: "clang", cxx: "clang++", flags: "-flto -ffunction-sections -fuse-ld=lld -Wno-unused-command-line-argument"}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
@@ -198,12 +340,12 @@ jobs:
|
||||
uses: eine/setup-msys2@v2
|
||||
with:
|
||||
update: true
|
||||
install: mingw-w64-x86_64-toolchain mingw-w64-x86_64-cmake make
|
||||
install: mingw-w64-x86_64-toolchain mingw-w64-x86_64-clang mingw-w64-x86_64-lld mingw-w64-x86_64-cmake make
|
||||
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -G "Unix Makefiles" -DCMAKE_C_FLAGS="-Os" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
cmake . -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_C_FLAGS="-Os ${{ matrix.config.flags }}" -DCURL_TARGET_WINDOWS_VERSION=0x0600 -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j$(nproc)
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
@@ -212,7 +354,7 @@ jobs:
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "Unix Makefiles" -DCMAKE_C_FLAGS='-Os' -DBUILD_TESTING=OFF
|
||||
cmake .. -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build libzmq
|
||||
@@ -220,22 +362,27 @@ jobs:
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "Unix Makefiles" -DCMAKE_C_FLAGS='-Os' -DCMAKE_CXX_FLAGS='-Os' -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DZMQ_HAVE_IPC=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DWITH_PERF_TOOL=OFF
|
||||
cmake .. -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cxx }} -DCMAKE_C_FLAGS='-Os ${{ matrix.config.flags }}' -DCMAKE_CXX_FLAGS='-Os ${{ matrix.config.flags }}' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DZMQ_HAVE_IPC=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "Unix Makefiles" -DSTATIC_LIBS=ON
|
||||
cmake .. -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cxx }} -DCMAKE_C_FLAGS="${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections" -DCMAKE_CXX_FLAGS="${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections" -DSTATIC_LIBS=ON
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run RandomX tests
|
||||
run: |
|
||||
build/p2pool.exe --test
|
||||
build/external/src/RandomX/randomx-tests.exe
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "Unix Makefiles" -DSTATIC_LIBS=ON
|
||||
cmake .. -G "Unix Makefiles" -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cxx }} -DCMAKE_C_FLAGS="${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections" -DCMAKE_CXX_FLAGS="${{ matrix.config.flags }} -Wl,-s -Wl,--gc-sections" -DSTATIC_LIBS=ON
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run tests
|
||||
@@ -247,7 +394,7 @@ jobs:
|
||||
- name: Archive binary
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool-msys2.exe
|
||||
name: p2pool-msys2-${{ matrix.config.c }}.exe
|
||||
path: build/p2pool.exe
|
||||
|
||||
build-windows-msbuild:
|
||||
@@ -258,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
|
||||
@@ -276,7 +423,23 @@ jobs:
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "${{ matrix.config.vs }}" -DWITH_RANDOMX=${{ matrix.config.rx }} -DWITH_UPNP=${{ matrix.config.upnp }}
|
||||
& "${{ matrix.config.msbuild }}msbuild" /m /p:Configuration=Release p2pool.vcxproj
|
||||
& "${{ matrix.config.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.vspath }}\\MSBuild\\Current\\Bin\\amd64\\msbuild" -v:m /m /p:Configuration=Release randomx-tests.vcxproj
|
||||
Release/randomx-tests.exe
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
@@ -284,7 +447,7 @@ jobs:
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "${{ matrix.config.vs }}"
|
||||
& "${{ matrix.config.msbuild }}msbuild" /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: |
|
||||
@@ -295,17 +458,13 @@ 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:
|
||||
|
||||
timeout-minutes: 15
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-11, macos-12]
|
||||
timeout-minutes: 20
|
||||
runs-on: macos-11
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@@ -313,13 +472,10 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake
|
||||
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_FLAGS="-Os" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
cmake . -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-Os -flto" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j3
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
@@ -328,7 +484,7 @@ jobs:
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os' -DBUILD_TESTING=OFF
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-Os -flto' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j3
|
||||
|
||||
- name: Build libzmq
|
||||
@@ -336,22 +492,27 @@ jobs:
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os' -DCMAKE_CXX_FLAGS='-Os' -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DWITH_PERF_TOOL=OFF
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-Os -flto' -DCMAKE_CXX_FLAGS='-Os -flto' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j3
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DSTATIC_BINARY=ON
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-flto" -DCMAKE_CXX_FLAGS="-flto" -DSTATIC_LIBS=ON
|
||||
make -j3
|
||||
|
||||
- name: Run RandomX tests
|
||||
run: |
|
||||
build/p2pool --test
|
||||
build/external/src/RandomX/randomx-tests
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cd tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DSTATIC_LIBS=ON
|
||||
cmake .. -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS="-flto" -DCMAKE_CXX_FLAGS="-flto" -DSTATIC_LIBS=ON
|
||||
make -j3
|
||||
|
||||
- name: Run tests
|
||||
@@ -363,17 +524,13 @@ jobs:
|
||||
- name: Archive binary
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool-${{ matrix.os }}
|
||||
name: p2pool-macos-11
|
||||
path: build/p2pool
|
||||
|
||||
build-macos-aarch64:
|
||||
|
||||
timeout-minutes: 15
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
os: [macos-11, macos-12]
|
||||
timeout-minutes: 20
|
||||
runs-on: macos-11
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@@ -381,13 +538,10 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake
|
||||
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_FLAGS='-Os -target arm64-apple-${{ matrix.os }}' -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
cmake . -DCMAKE_C_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
|
||||
|
||||
@@ -396,7 +550,7 @@ jobs:
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os -target arm64-apple-${{ matrix.os }}' -DBUILD_TESTING=OFF
|
||||
cmake .. -DCMAKE_C_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
|
||||
@@ -404,20 +558,20 @@ jobs:
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os -target arm64-apple-${{ matrix.os }}' -DCMAKE_CXX_FLAGS='-Os -target arm64-apple-${{ matrix.os }}' -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DWITH_PERF_TOOL=OFF
|
||||
cmake .. -DCMAKE_C_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_FLAGS='-target arm64-apple-${{ matrix.os }}' -DCMAKE_CXX_FLAGS='-target arm64-apple-${{ matrix.os }}' -DSTATIC_BINARY=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
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool-${{ matrix.os }}-aarch64
|
||||
name: p2pool-macos-11-aarch64
|
||||
path: build/p2pool
|
||||
|
||||
build-freebsd:
|
||||
@@ -440,7 +594,7 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Build p2pool
|
||||
uses: cross-platform-actions/action@v0.10.0
|
||||
uses: cross-platform-actions/action@v0.19.0
|
||||
with:
|
||||
operating_system: ${{ matrix.os.name }}
|
||||
architecture: ${{ matrix.os.architecture }}
|
||||
@@ -449,28 +603,30 @@ jobs:
|
||||
run: |
|
||||
sudo pkg install -y cmake
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_FLAGS="-Os" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
cmake . -DCMAKE_C_FLAGS="-Os -flto" -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j2
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
cd ../../libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os' -DBUILD_TESTING=OFF
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os -flto' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j2
|
||||
cd ../../libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os' -DCMAKE_CXX_FLAGS='-Os' -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DWITH_PERF_TOOL=OFF
|
||||
cmake .. -DCMAKE_C_FLAGS='-Os -flto' -DCMAKE_CXX_FLAGS='-Os -flto' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j2
|
||||
cd ../../../..
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DSTATIC_BINARY=ON
|
||||
cmake .. -DCMAKE_C_FLAGS='-flto' -DCMAKE_CXX_FLAGS='-flto' -DSTATIC_LIBS=ON
|
||||
make -j2
|
||||
./p2pool --test
|
||||
external/src/RandomX/randomx-tests
|
||||
cd ../tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DSTATIC_LIBS=ON
|
||||
cmake .. -DCMAKE_C_FLAGS='-flto' -DCMAKE_CXX_FLAGS='-flto' -DSTATIC_LIBS=ON
|
||||
make -j2
|
||||
gunzip *.gz
|
||||
./p2pool_tests
|
||||
@@ -501,7 +657,7 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Build p2pool
|
||||
uses: cross-platform-actions/action@v0.10.0
|
||||
uses: cross-platform-actions/action@v0.19.0
|
||||
with:
|
||||
operating_system: ${{ matrix.os.name }}
|
||||
architecture: ${{ matrix.os.architecture }}
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
name: clang-tidy
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
- 'README.md'
|
||||
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
clang-tidy:
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
@@ -17,9 +23,9 @@ jobs:
|
||||
run: |
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 16
|
||||
sudo apt-get install -y clang-tidy-16
|
||||
clang-tidy-16 --verify-config
|
||||
sudo ./llvm.sh 17
|
||||
sudo apt-get install -y clang-tidy-17
|
||||
clang-tidy-17 --verify-config
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
@@ -30,9 +36,9 @@ jobs:
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_C_COMPILER=clang-16 -DCMAKE_CXX_COMPILER=clang++-16 -DDEV_CLANG_TIDY=ON
|
||||
cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DDEV_CLANG_TIDY=ON
|
||||
|
||||
- name: Run clang-tidy
|
||||
run: |
|
||||
cd src
|
||||
clang-tidy-16 *.cpp -p ../build -checks=-clang-diagnostic-undefined-internal -warnings-as-errors=* -header-filter=^[^\.]
|
||||
clang-tidy-17 *.cpp -p ../build -checks=-clang-diagnostic-undefined-internal -warnings-as-errors=* -header-filter=^[^\.]
|
||||
|
||||
@@ -13,7 +13,13 @@ name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
- 'README.md'
|
||||
|
||||
pull_request:
|
||||
|
||||
schedule:
|
||||
- cron: '44 11 * * 0'
|
||||
|
||||
|
||||
@@ -2,7 +2,13 @@ name: cppcheck
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
- 'README.md'
|
||||
|
||||
pull_request:
|
||||
|
||||
schedule:
|
||||
- cron: '57 0 * * *'
|
||||
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
name: Build libc++ for MemorySanitizer
|
||||
|
||||
on: [workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
build-libcxx_msan:
|
||||
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y git cmake ninja-build
|
||||
|
||||
- name: Install clang
|
||||
run: |
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 16
|
||||
|
||||
- name: Build libcxx_msan
|
||||
run: |
|
||||
git clone --depth=1 https://github.com/llvm/llvm-project -b release/16.x
|
||||
cd llvm-project
|
||||
mkdir build
|
||||
cmake -G Ninja -S runtimes -B build -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" -DCMAKE_C_COMPILER=clang-16 -DCMAKE_CXX_COMPILER=clang++-16 -DLLVM_USE_SANITIZER=MemoryWithOrigins
|
||||
ninja -C build cxx cxxabi
|
||||
cd build
|
||||
XZ_OPT=-e9 tar cfJ libcxx_msan.tar.xz include lib
|
||||
|
||||
- name: Archive libcxx_msan.tar.xz
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: libcxx_msan
|
||||
path: llvm-project/build/libcxx_msan.tar.xz
|
||||
@@ -10,7 +10,13 @@ name: Microsoft C++ Code Analysis
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
- 'README.md'
|
||||
|
||||
pull_request:
|
||||
|
||||
schedule:
|
||||
- cron: '40 10 * * 0'
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
name: source-snapshot
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
source-snapshot:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Compress source code
|
||||
run: |
|
||||
mkdir build
|
||||
XZ_OPT=-e9 tar --exclude=".git" --exclude="build" -f build/p2pool_source.tar.xz -c ../p2pool --xz
|
||||
|
||||
- name: Archive source code
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool_source.tar.xz
|
||||
path: build/p2pool_source.tar.xz
|
||||
+156
-31
@@ -2,7 +2,13 @@ name: Sync test
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
- 'README.md'
|
||||
|
||||
pull_request:
|
||||
|
||||
schedule:
|
||||
- cron: '17 0/3 * * *'
|
||||
|
||||
@@ -17,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
|
||||
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
|
||||
@@ -38,7 +67,11 @@ 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: |
|
||||
cd build
|
||||
grep 'Synchronization finished successfully' p2pool.log
|
||||
|
||||
- name: Archive p2pool.log
|
||||
@@ -50,7 +83,6 @@ jobs:
|
||||
build/data/
|
||||
|
||||
sync-test-ubuntu-msan:
|
||||
|
||||
timeout-minutes: 30
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
@@ -58,30 +90,35 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y git build-essential cmake libuv1-dev libzmq3-dev libsodium-dev libpgm-dev libnorm-dev libgss-dev libcurl4-openssl-dev libidn2-0-dev
|
||||
sudo apt install -y git build-essential cmake ninja-build
|
||||
|
||||
- name: Install clang
|
||||
run: |
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 16
|
||||
sudo ./llvm.sh 17
|
||||
|
||||
- name: Build libcxx_msan
|
||||
run: |
|
||||
git clone --depth=1 https://github.com/llvm/llvm-project -b release/17.x
|
||||
cd llvm-project
|
||||
mkdir build
|
||||
cmake -G Ninja -S runtimes -B build -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DLLVM_USE_SANITIZER=MemoryWithOrigins
|
||||
ninja -C build cxx cxxabi
|
||||
cd build
|
||||
mkdir /tmp/libcxx_msan
|
||||
cp -r include /tmp/libcxx_msan
|
||||
cp -r lib /tmp/libcxx_msan
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Install libcxx_msan
|
||||
run: |
|
||||
mkdir /tmp/libcxx_msan
|
||||
cp tests/src/libcxx_msan.tar.xz /tmp/libcxx_msan
|
||||
cd /tmp/libcxx_msan
|
||||
tar xvf libcxx_msan.tar.xz
|
||||
|
||||
- name: Build libcurl
|
||||
run: |
|
||||
cd external/src/curl
|
||||
cmake . -DCMAKE_C_COMPILER=clang-16 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g' -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
cmake . -DCMAKE_C_COMPILER=clang-17 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g' -DBUILD_CURL_EXE=OFF -DBUILD_SHARED_LIBS=OFF -DCURL_ZLIB=OFF -DCURL_DISABLE_ALTSVC=ON -DCURL_DISABLE_COOKIES=ON -DCURL_DISABLE_DOH=ON -DCURL_DISABLE_GETOPTIONS=ON -DCURL_DISABLE_HSTS=ON -DCURL_DISABLE_LIBCURL_OPTION=ON -DCURL_DISABLE_MIME=ON -DCURL_DISABLE_NETRC=ON -DCURL_DISABLE_NTLM=ON -DCURL_DISABLE_PARSEDATE=ON -DCURL_DISABLE_PROGRESS_METER=ON -DCURL_DISABLE_SHUFFLE_DNS=ON -DCURL_DISABLE_SOCKETPAIR=ON -DCURL_DISABLE_VERBOSE_STRINGS=ON -DHTTP_ONLY=ON -DCURL_ENABLE_SSL=OFF -DUSE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF -DENABLE_UNIX_SOCKETS=OFF
|
||||
make -j$(nproc)
|
||||
cd lib && mkdir .libs && cp libcurl.a .libs
|
||||
|
||||
@@ -90,7 +127,7 @@ jobs:
|
||||
cd external/src/libuv
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=clang-16 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g' -DBUILD_TESTING=OFF
|
||||
cmake .. -DCMAKE_C_COMPILER=clang-17 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g' -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build libzmq
|
||||
@@ -98,14 +135,14 @@ jobs:
|
||||
cd external/src/libzmq
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=clang-16 -DCMAKE_CXX_COMPILER=clang++-16 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g' -DCMAKE_CXX_FLAGS='-nostdinc++ -nostdlib++ -fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g -isystem /tmp/libcxx_msan/include/c++/v1 -L/tmp/libcxx_msan/lib -lc++ -lc++abi -Wno-unused-command-line-argument' -DWITH_TLS=OFF -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DWITH_PERF_TOOL=OFF
|
||||
cmake .. -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g' -DCMAKE_CXX_FLAGS='-nostdinc++ -nostdlib++ -fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -Os -fno-omit-frame-pointer -g -isystem /tmp/libcxx_msan/include/c++/v1 -L/tmp/libcxx_msan/lib -lc++ -lc++abi -Wno-unused-command-line-argument' -DWITH_LIBSODIUM=OFF -DWITH_LIBBSD=OFF -DBUILD_TESTS=OFF -DWITH_DOCS=OFF -DENABLE_DRAFTS=OFF -DBUILD_SHARED=OFF
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_C_COMPILER=clang-16 -DCMAKE_CXX_COMPILER=clang++-16 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -fno-omit-frame-pointer -g' -DCMAKE_CXX_FLAGS='-nostdinc++ -nostdlib++ -fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -isystem /tmp/libcxx_msan/include/c++/v1 -L/tmp/libcxx_msan/lib -Wl,-rpath /tmp/libcxx_msan/lib -lc++ -lc++abi -Wno-unused-command-line-argument -fuse-ld=lld-16 -fno-omit-frame-pointer -g' -DDEV_TEST_SYNC=ON -DDEV_WITH_MSAN=ON -DSTATIC_LIBS=ON
|
||||
cmake .. -DCMAKE_C_COMPILER=clang-17 -DCMAKE_CXX_COMPILER=clang++-17 -DCMAKE_C_FLAGS='-fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -fno-omit-frame-pointer -g' -DCMAKE_CXX_FLAGS='-nostdinc++ -nostdlib++ -fsanitize=memory -fsanitize-recover -fsanitize-memory-track-origins -isystem /tmp/libcxx_msan/include/c++/v1 -L/tmp/libcxx_msan/lib -Wl,-rpath /tmp/libcxx_msan/lib -lc++ -lc++abi -Wno-unused-command-line-argument -fuse-ld=lld-17 -fno-omit-frame-pointer -g' -DDEV_TEST_SYNC=ON -DDEV_WITH_MSAN=ON -DSTATIC_LIBS=ON
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run p2pool
|
||||
@@ -115,7 +152,11 @@ 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: |
|
||||
cd build
|
||||
grep 'Synchronization finished successfully' p2pool.log
|
||||
|
||||
- name: Archive p2pool.log
|
||||
@@ -147,7 +188,7 @@ jobs:
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_UBSAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12
|
||||
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_UBSAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_C_FLAGS="-flto=2" -DCMAKE_CXX_FLAGS="-flto=2"
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run p2pool
|
||||
@@ -157,7 +198,11 @@ 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: |
|
||||
cd build
|
||||
grep 'Synchronization finished successfully' p2pool.log
|
||||
|
||||
- name: Archive p2pool.log
|
||||
@@ -189,7 +234,7 @@ jobs:
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_ASAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12
|
||||
cmake .. -DDEV_TEST_SYNC=ON -DDEV_WITH_ASAN=ON -DCMAKE_C_COMPILER=gcc-12 -DCMAKE_CXX_COMPILER=g++-12 -DCMAKE_C_FLAGS="-flto=2" -DCMAKE_CXX_FLAGS="-flto=2"
|
||||
make -j$(nproc)
|
||||
|
||||
- name: Run p2pool
|
||||
@@ -199,7 +244,11 @@ 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: |
|
||||
cd build
|
||||
grep 'Synchronization finished successfully' p2pool.log
|
||||
|
||||
- name: Archive p2pool.log
|
||||
@@ -213,7 +262,7 @@ jobs:
|
||||
sync-test-macos:
|
||||
|
||||
timeout-minutes: 30
|
||||
runs-on: macos-12
|
||||
runs-on: macos-11
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@@ -222,23 +271,52 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install cmake libuv zmq libpgm curl
|
||||
run: |
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install 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
|
||||
run: |
|
||||
cd build
|
||||
mkdir data
|
||||
python ../tests/src/stratum_dummy.py 1 &
|
||||
python ../tests/src/stratum_dummy.py 2 &
|
||||
python ../tests/src/stratum_dummy.py 3 &
|
||||
./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
|
||||
python3 ../tests/src/stratum_dummy.py 1 &
|
||||
python3 ../tests/src/stratum_dummy.py 2 &
|
||||
python3 ../tests/src/stratum_dummy.py 3 &
|
||||
./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
cd build
|
||||
grep 'Synchronization finished successfully' p2pool.log
|
||||
|
||||
- name: Archive p2pool.log
|
||||
@@ -268,7 +346,7 @@ jobs:
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "Visual Studio 17 2022" -DDEV_TEST_SYNC=ON
|
||||
& "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\msbuild" /m /p:Configuration=Debug p2pool.vcxproj
|
||||
& "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\msbuild" -v:m /m /p:Configuration=Debug p2pool.vcxproj
|
||||
|
||||
- name: Run p2pool
|
||||
run: |
|
||||
@@ -277,7 +355,11 @@ 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: |
|
||||
cd build/Debug
|
||||
findstr /C:"Synchronization finished successfully" p2pool.log
|
||||
|
||||
- name: Archive p2pool.log
|
||||
@@ -287,3 +369,46 @@ jobs:
|
||||
path: |
|
||||
build/Debug/*.log
|
||||
build/Debug/data/
|
||||
|
||||
sync-test-windows-leaks:
|
||||
|
||||
timeout-minutes: 30
|
||||
runs-on: windows-2022
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup cmake
|
||||
uses: lukka/get-cmake@latest
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G "Visual Studio 17 2022" -DDEV_TEST_SYNC=ON -DDEV_TRACK_MEMORY=ON
|
||||
& "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\msbuild" -v:m /m /p:Configuration=RelWithDebInfo p2pool.vcxproj
|
||||
|
||||
- name: Run p2pool
|
||||
run: |
|
||||
cd build/RelWithDebInfo
|
||||
mkdir data
|
||||
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 1"
|
||||
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 2"
|
||||
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 3"
|
||||
./p2pool.exe --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
cd build/RelWithDebInfo
|
||||
findstr /C:"Synchronization finished successfully" p2pool.log
|
||||
|
||||
- name: Archive p2pool.log
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: p2pool_windows_data_leaks
|
||||
path: |
|
||||
build/RelWithDebInfo/*.log
|
||||
build/RelWithDebInfo/data/
|
||||
|
||||
+18
-2
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(p2pool)
|
||||
|
||||
option(STATIC_BINARY "Build static binary" OFF)
|
||||
@@ -13,6 +13,7 @@ option(DEV_WITH_MSAN "[Developer only] Compile with memory sanitizer" OFF)
|
||||
option(DEV_WITH_UBSAN "[Developer only] Compile with undefined behavior sanitizer" OFF)
|
||||
option(DEV_WITH_ASAN "[Developer only] Compile with address sanitizer" OFF)
|
||||
option(DEV_CLANG_TIDY "[Developer only] Compile for clang-tidy" OFF)
|
||||
option(DEV_TRACK_MEMORY "[Developer only] Track memory allocations" OFF)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake")
|
||||
|
||||
@@ -56,6 +57,10 @@ if (DEV_CLANG_TIDY)
|
||||
add_definitions(-DDEV_CLANG_TIDY)
|
||||
endif()
|
||||
|
||||
if (DEV_TRACK_MEMORY)
|
||||
add_definitions(-DDEV_TRACK_MEMORY)
|
||||
endif()
|
||||
|
||||
include(cmake/flags.cmake)
|
||||
|
||||
set(HEADERS
|
||||
@@ -159,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)
|
||||
@@ -313,6 +320,8 @@ if (STATIC_BINARY OR STATIC_LIBS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(STATIC_LIBS "")
|
||||
|
||||
if (WITH_RANDOMX)
|
||||
set(STATIC_LIBS randomx)
|
||||
endif()
|
||||
@@ -323,7 +332,7 @@ if (STATIC_BINARY OR STATIC_LIBS)
|
||||
|
||||
if (WIN32)
|
||||
set(STATIC_LIBS ${STATIC_LIBS} ws2_32 iphlpapi userenv psapi dnsapi dbghelp)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
if ((CMAKE_CXX_COMPILER_ID MATCHES GNU) OR (CMAKE_CXX_COMPILER_ID MATCHES Clang))
|
||||
set(STATIC_LIBS ${STATIC_LIBS} bcrypt)
|
||||
endif()
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
|
||||
@@ -350,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}
|
||||
")
|
||||
|
||||
@@ -22,7 +22,7 @@ These are 3rd-party pages. If they are down, it doesn't mean there is a problem
|
||||
# Contents
|
||||
- [Pool mining vs Solo mining vs P2Pool mining](#pool-mining-vs-solo-mining-vs-p2pool-mining)
|
||||
- [Features](#features)
|
||||
- [How PPLNS works in P2Pool](#how-pplns-works-in-p2pool)
|
||||
- [How payouts work in P2Pool](#how-payouts-work-in-p2pool)
|
||||
- [Default P2Pool parameters](#default-p2pool-parameters)
|
||||
- [Monero version support](#monero-version-support)
|
||||
- [How to mine on P2Pool](#how-to-mine-on-p2pool)
|
||||
@@ -41,17 +41,17 @@ Here's the comparison table of the different ways of mining. While pool mining i
|
||||
|-|-|-|-|-|-|-|-|
|
||||
|Centralized pool|Regular|0-3%|0.001-0.01 XMR|Yes|Less stable due to pool server outages|Pool admin controls your mined funds, what you mine and can execute network attacks|Only miner software is required
|
||||
|Solo|Rare|0%|0.6 XMR or more|No|As stable as your Monero node|100% under your control|Monero node + optional miner
|
||||
|**P2Pool**|Regular|0%|~0.00027 XMR|No|Very stable: node failover and multiple Monero nodes are supported|100% under your control|Monero node(s) + P2Pool node(s) + miner(s)
|
||||
|**P2Pool**|Regular|0%|~0.00027 XMR|No|Very stable: node failover and multiple Monero nodes are supported|100% under your control|Monero node(s) + P2Pool node(s) + optional miner(s)
|
||||
|
||||
## Features
|
||||
|
||||
* 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**
|
||||
* **~0.0003 XMR minimal payout**
|
||||
* **~0.00027 XMR minimal payout**
|
||||
* Fast block times, down to 1 second
|
||||
* Uncle blocks are supported to avoid orphans - all your shares will be accounted for!
|
||||
* Configurable PPLNS window size and block time
|
||||
@@ -59,25 +59,28 @@ Here's the comparison table of the different ways of mining. While pool mining i
|
||||
* Password protected private pools
|
||||
* Highly reliable configurations are supported (multiple P2Pool nodes mining to the same wallet, each P2Pool node can use multiple Monero nodes and switch on the fly if an issue is detected)
|
||||
|
||||
## How PPLNS works in P2Pool
|
||||
## How payouts work in P2Pool
|
||||
|
||||
First you need to find a pool share. This share will stay in PPLNS window for 2160 pool blocks (6 hours). The moment P2Pool finds a Monero block and you have at least 1 pool share in PPLNS window, you'll get a payout! Monero block reward is split between all miner wallets in PPLNS window. Each miner gets a part of block reward proportional to the total difficulty of his/her shares in PPLNS window.
|
||||
First you need to find a pool share. This share will stay in [PPLNS](https://en.wikipedia.org/wiki/Mining_pool#Pay-per-last-N-shares) window for up to 2160 pool blocks (6 hours, auto adjustable to balance payout sizes and frequency). The moment P2Pool finds a Monero block and you have at least 1 pool share in PPLNS window, you'll get a payout! Monero block reward is split between all miner wallets in PPLNS window. Each miner gets a part of block reward proportional to the total difficulty of his/her shares in PPLNS window.
|
||||
|
||||
**NOTE** If P2Pool doesn't have enough hashrate to find Monero blocks faster than every 6 hours on average (~15 MH/s), **not all your pool shares will result in a payout**. Even if pool hashrate is higher, bad luck can sometimes result in a share going through PPLNS window without a payout. But in the long run it will be compensated by other shares receiving multiple payouts - your payouts will average out to what you'd get with regular pool mining.
|
||||
|
||||
## Default P2Pool parameters
|
||||
|
||||
* Block time: 10 seconds
|
||||
* PPLNS window: up to 2160 blocks (6 hours), auto adjustable to balance payout sizes and frequency
|
||||
* Minimum payout = Monero block reward/2160, ~0.0003 XMR
|
||||
* PPLNS window: up to 2160 blocks (6 hours, auto adjustable to balance payout sizes and frequency)
|
||||
* Minimum payout = Monero block reward/2160, ~0.00027 XMR
|
||||
|
||||
## Monero version support
|
||||
|
||||
Monero network upgrade happened on August 13th, 2022 (block 2,688,888). In order to continue mining, you must update both Monero and P2Pool software to the latest available versions as soon as they are released.
|
||||
- The latest Monero network upgrade happened on August 13th, 2022 (block 2,688,888).
|
||||
- The latest P2Pool network upgrade happened on March 18th, 2023 at 21:00 UTC.
|
||||
|
||||
In order to continue mining on P2Pool, you must update both Monero and P2Pool software to the latest available versions as soon as they are released.
|
||||
|
||||
|Monero protocol version|Required Monero software version|Required P2Pool version
|
||||
|-|-|-|
|
||||
|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
|
||||
|
||||
@@ -85,7 +88,7 @@ Monero network upgrade happened on August 13th, 2022 (block 2,688,888). In order
|
||||
|
||||
- In order to mine on P2Pool, a synced Monero node using monerod v0.18.0.0 or newer is required. If you don't currently have one, you can download the official Monero binaries, start `monerod` on your PC and wait until it's fully synced. Advanced Monero node setup instructions are [here](https://sethforprivacy.com/guides/run-a-monero-node-advanced/).
|
||||
- It is highly recommended that you create a separate restricted user account (in your OS) for mining. While P2Pool has been battle-tested for a long time now, any software may have unknown bugs/vulnerabilities.
|
||||
- You have to use a primary wallet address for mining. Subaddresses and integrated addresses are not supported, just like with monerod solo mining.
|
||||
- You have to use a primary wallet address (the one starting with `4`) for mining. Subaddresses and integrated addresses are not supported, just like with monerod solo mining.
|
||||
- You can add the `--mini` parameter to your P2Pool command to connect to the **p2pool-mini** sidechain. Note that it will also change the default p2p port from 37889 to 37888.
|
||||
- Check that ports 18080 (Monero p2p port) and 37889/37888 (P2Pool/P2Pool mini p2p port) are open in your firewall to ensure better connectivity. If you're mining from a computer behind NAT (like a router) you could consider forwarding the ports to your local machine.
|
||||
- You can connect multiple miners to the same P2Pool node. The more the better!
|
||||
@@ -109,21 +112,21 @@ Monero network upgrade happened on August 13th, 2022 (block 2,688,888). In order
|
||||
1. Download the latest P2Pool binaries [here](https://github.com/SChernykh/p2pool/releases/latest).
|
||||
- Alternatively, grab the latest source code for P2Pool and [build it](#build-instructions).
|
||||
2. Download the latest XMRig (linux-static-x64) binary [here](https://github.com/xmrig/xmrig/releases/latest).
|
||||
3. Prepare enough huge pages (required for each instance of monerod/P2Pool/XMRig):
|
||||
3. Prepare enough huge pages (each of monerod/P2Pool/XMRig needs them):
|
||||
```
|
||||
sudo sysctl vm.nr_hugepages=3072
|
||||
```
|
||||
4. Check that ports 18080 (Monero p2p port) and 37889/37888 (P2Pool/P2Pool mini p2p port) are open in your local firewall to ensure better connectivity.
|
||||
5. Start `monerod` with the following command/options:
|
||||
```
|
||||
./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=node.supportxmr.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
|
||||
./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 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=node.supportxmr.com:18080 --add-priority-node=nodes.hashvault.pro:18080` is needed to have guaranteed good working nodes in your connected peers.
|
||||
`--add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080` is needed to have guaranteed good working nodes in your connected peers.
|
||||
|
||||
`--disable-dns-checkpoints` is needed to avoid periodical lags when DNS is updated (it's not needed when mining)
|
||||
|
||||
@@ -174,7 +177,7 @@ nocreate
|
||||
2. Download the latest XMRig binary [here](https://github.com/xmrig/xmrig/releases/latest).
|
||||
3. Expand the P2Pool binaries into an appropriate location (`%USERPROFILE%/bin` or `C:/bin/` are good options)
|
||||
4. Expand XMRig binary into an appropriate location (the same folder as P2Pool is fine).
|
||||
5. Prepare huge pages to work properly (each instance of monerod/P2Pool/XMRig needs them):
|
||||
5. Prepare huge pages to work properly (each of monerod/P2Pool/XMRig needs them):
|
||||
- On Windows 10 or above, run XMRig at least once as Administrator (right-click Run As Administrator)
|
||||
- On earlier versions of Windows, you'll need to run XMRig as Administrator at least once per login.
|
||||
6. Create "Monero" folder inside extracted P2Pool folder and copy Monero binaries there.
|
||||
@@ -184,14 +187,14 @@ nocreate
|
||||
|
||||
8. Start `monerod` with the following command/options:
|
||||
```
|
||||
.\Monero\monerod.exe --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=node.supportxmr.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
|
||||
.\Monero\monerod.exe --zmq-pub tcp://127.0.0.1:18083 --out-peers 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=node.supportxmr.com:18080 --add-priority-node=nodes.hashvault.pro:18080` is needed to have guaranteed good working nodes in your connected peers.
|
||||
`--add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080` is needed to have guaranteed good working nodes in your connected peers.
|
||||
|
||||
`--disable-dns-checkpoints` is needed to avoid periodical lags when DNS is updated (it's not needed when mining)
|
||||
|
||||
@@ -215,7 +218,7 @@ The `--zmq-pub` option is required for P2Pool to work properly.
|
||||
13. *(Optional but highly recommended)* You can create a Quickstart by creating a batch (.bat) file with the following contents and placing it in your P2Pool directory along with `xmrig.exe`.
|
||||
```
|
||||
@ECHO OFF
|
||||
start cmd /k %~dp0\Monero\monerod.exe --zmq-pub tcp://127.0.0.1:18083 --out-peers 64 --in-peers 32 --add-priority-node=node.supportxmr.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --disable-dns-checkpoints --enable-dns-blocklist
|
||||
start cmd /k %~dp0\Monero\monerod.exe --zmq-pub tcp://127.0.0.1:18083 --out-peers 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
|
||||
|
||||
+30
-3
@@ -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")
|
||||
@@ -68,10 +83,22 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
set(GENERAL_FLAGS "-pthread")
|
||||
if (WIN32)
|
||||
set(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 (NOT DEV_WITH_MSAN)
|
||||
if (DEV_WITH_MSAN)
|
||||
set(OPTIMIZATION_FLAGS "-O2 -g")
|
||||
else()
|
||||
set(OPTIMIZATION_FLAGS "-Ofast -funroll-loops -fmerge-all-constants")
|
||||
endif()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
### P2Pool console commands
|
||||
|
||||
Command|Description
|
||||
-|-
|
||||
help|display list of commands
|
||||
status|display p2pool status
|
||||
loglevel **N**|set log level (**N** can be between 0 and 6)
|
||||
addpeers **L**|**L** is a comma-separated list of IP:port of other p2pool nodes to connect to
|
||||
droppeers|disconnect all currently connected peers
|
||||
peers|show all currently connected peers (p2p)
|
||||
workers|show all currently connected workers (stratum)
|
||||
bans|show all banned IPs
|
||||
hosts|show Monero hosts which were configured in the command line
|
||||
next_host|switch to the next Monero host configured in the command line
|
||||
outpeers **N**|set maximum number of outgoing connections (values above 50 are not recommended)
|
||||
inpeers **N**|set maximum number of incoming connections (values above 50 are not recommended)
|
||||
start_mining **T**|start mining (**T** is the number of threads to use, must be between 1 and 64)
|
||||
stop_mining|stop mining
|
||||
exit|terminate p2pool
|
||||
version|show p2pool version
|
||||
+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=node.supportxmr.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=node.supportxmr.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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Vendored
+1
-1
Submodule external/src/RandomX updated: 59d1483ad7...80d9f08b4f
Vendored
+1
-1
Submodule external/src/cppzmq updated: c66fc6094b...c94c20743e
Vendored
+1
-1
Submodule external/src/curl updated: 046209e561...50490c0679
Vendored
+1
-1
Submodule external/src/libuv updated: 7bb8ba6afc...26d43f49ff
Vendored
+1
-1
Submodule external/src/libzmq updated: 532b61275e...ec013f3a17
Vendored
+1
-1
Submodule external/src/miniupnp updated: cb3650edba...f7b437772b
Vendored
+1
-1
Submodule external/src/rapidjson updated: 678281bbdb...128cc9359f
+1
-1
@@ -20,7 +20,7 @@
|
||||
#include "pool_block.h"
|
||||
#include "p2p_server.h"
|
||||
|
||||
static constexpr char log_category_prefix[] = "BlockCache ";
|
||||
LOG_CATEGORY(BlockCache)
|
||||
|
||||
static constexpr uint32_t BLOCK_SIZE = 96 * 1024;
|
||||
static constexpr uint32_t NUM_BLOCKS = 4608;
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <ctime>
|
||||
#include <numeric>
|
||||
|
||||
static constexpr char log_category_prefix[] = "BlockTemplate ";
|
||||
LOG_CATEGORY(BlockTemplate)
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
@@ -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
|
||||
|
||||
+17
-5
@@ -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);
|
||||
@@ -152,8 +161,8 @@ struct alignas(uint64_t) hash
|
||||
|
||||
FORCEINLINE bool operator<(const hash& other) const
|
||||
{
|
||||
const uint64_t* a = reinterpret_cast<const uint64_t*>(h);
|
||||
const uint64_t* b = reinterpret_cast<const uint64_t*>(other.h);
|
||||
const uint64_t* a = u64();
|
||||
const uint64_t* b = other.u64();
|
||||
|
||||
if (a[3] < b[3]) return true;
|
||||
if (a[3] > b[3]) return false;
|
||||
@@ -169,18 +178,21 @@ struct alignas(uint64_t) hash
|
||||
|
||||
FORCEINLINE bool operator==(const hash& other) const
|
||||
{
|
||||
const uint64_t* a = reinterpret_cast<const uint64_t*>(h);
|
||||
const uint64_t* b = reinterpret_cast<const uint64_t*>(other.h);
|
||||
const uint64_t* a = u64();
|
||||
const uint64_t* b = other.u64();
|
||||
return (a[0] == b[0]) && (a[1] == b[1]) && (a[2] == b[2]) && (a[3] == b[3]);
|
||||
}
|
||||
|
||||
FORCEINLINE bool operator!=(const hash& other) const { return !operator==(other); }
|
||||
|
||||
FORCEINLINE bool empty() const {
|
||||
const uint64_t* a = reinterpret_cast<const uint64_t*>(h);
|
||||
const uint64_t* a = u64();
|
||||
return (a[0] == 0) && (a[1] == 0) && (a[2] == 0) && (a[3] == 0);
|
||||
}
|
||||
|
||||
FORCEINLINE uint64_t* u64() { return reinterpret_cast<uint64_t*>(h); }
|
||||
FORCEINLINE const uint64_t* u64() const { return reinterpret_cast<const uint64_t*>(h); }
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& s, const hash& d);
|
||||
friend std::istream& operator>>(std::istream& s, hash& d);
|
||||
};
|
||||
|
||||
+75
-42
@@ -28,7 +28,7 @@
|
||||
#include "p2pool_api.h"
|
||||
#include "params.h"
|
||||
|
||||
static constexpr char log_category_prefix[] = "ConsoleCommands ";
|
||||
LOG_CATEGORY(ConsoleCommands)
|
||||
|
||||
static constexpr int DEFAULT_BACKLOG = 1;
|
||||
|
||||
@@ -47,7 +47,41 @@ ConsoleCommands::ConsoleCommands(p2pool* pool)
|
||||
LOGINFO(3, "uv_guess_handle returned " << static_cast<int>(stdin_type));
|
||||
if (stdin_type != UV_TTY && stdin_type != UV_NAMED_PIPE) {
|
||||
LOGERR(1, "tty or named pipe is not available");
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
int err;
|
||||
|
||||
if (stdin_type == UV_TTY) {
|
||||
LOGINFO(3, "processing stdin as UV_TTY");
|
||||
err = uv_tty_init(&m_loop, &m_tty, 0, 1);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_tty_init failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
m_stdin_handle = reinterpret_cast<uv_stream_t*>(&m_tty);
|
||||
}
|
||||
else if (stdin_type == UV_NAMED_PIPE) {
|
||||
LOGINFO(3, "processing stdin as UV_NAMED_PIPE");
|
||||
err = uv_pipe_init(&m_loop, &m_stdin_pipe, 0);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_pipe_init failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
m_stdin_handle = reinterpret_cast<uv_stream_t*>(&m_stdin_pipe);
|
||||
err = uv_pipe_open(&m_stdin_pipe, 0);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_pipe_open failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_stdin_handle) {
|
||||
m_stdin_handle->data = this;
|
||||
err = uv_read_start(m_stdin_handle, allocCallback, stdinReadCallback);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_read_start failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
|
||||
std::random_device rd;
|
||||
@@ -67,50 +101,29 @@ ConsoleCommands::ConsoleCommands(p2pool* pool)
|
||||
m_pool->api()->set(p2pool_api::Category::LOCAL, "console",
|
||||
[stdin_type, this](log::Stream& s)
|
||||
{
|
||||
s << "{\"mode\":" << ((stdin_type == UV_TTY) ? "\"tty\"" : "\"pipe\"")
|
||||
<< ",\"tcp_port\":" << m_listenPort
|
||||
<< "}";
|
||||
s << "{\"mode\":\"";
|
||||
|
||||
if (stdin_type == UV_TTY) {
|
||||
s << "tty";
|
||||
}
|
||||
else if (stdin_type == UV_NAMED_PIPE) {
|
||||
s << "pipe";
|
||||
}
|
||||
else {
|
||||
s << static_cast<int>(stdin_type);
|
||||
}
|
||||
|
||||
s << "\",\"tcp_port\":" << m_listenPort << '}';
|
||||
});
|
||||
}
|
||||
|
||||
int err;
|
||||
|
||||
if (stdin_type == UV_TTY) {
|
||||
LOGINFO(3, "processing stdin as UV_TTY");
|
||||
err = uv_tty_init(&m_loop, &m_tty, 0, 1);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_tty_init failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
m_stdin_handle = reinterpret_cast<uv_stream_t*>(&m_tty);
|
||||
}
|
||||
else {
|
||||
LOGINFO(3, "processing stdin as UV_NAMED_PIPE");
|
||||
err = uv_pipe_init(&m_loop, &m_stdin_pipe, 0);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_pipe_init failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
m_stdin_handle = reinterpret_cast<uv_stream_t*>(&m_stdin_pipe);
|
||||
err = uv_pipe_open(&m_stdin_pipe, 0);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_pipe_open failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
m_stdin_handle->data = this;
|
||||
|
||||
err = uv_read_start(m_stdin_handle, allocCallback, stdinReadCallback);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_read_start failed, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
err = uv_thread_create(&m_loopThread, loop, this);
|
||||
if (err) {
|
||||
LOGERR(1, "failed to start event loop thread, error " << uv_err_name(err));
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
m_loopThreadCreated = true;
|
||||
}
|
||||
|
||||
ConsoleCommands::~ConsoleCommands()
|
||||
@@ -120,7 +133,14 @@ ConsoleCommands::~ConsoleCommands()
|
||||
|
||||
void ConsoleCommands::on_shutdown()
|
||||
{
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(m_stdin_handle), nullptr);
|
||||
if (m_stdin_handle) {
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(m_stdin_handle), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
const char* ConsoleCommands::get_log_category() const
|
||||
{
|
||||
return log_category_prefix;
|
||||
}
|
||||
|
||||
typedef struct strconst {
|
||||
@@ -182,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)
|
||||
@@ -292,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)
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
void on_shutdown() override;
|
||||
|
||||
private:
|
||||
const char* get_category() const override { return "ConsoleCommands "; }
|
||||
const char* get_log_category() const override;
|
||||
|
||||
p2pool* m_pool;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "json_rpc_request.h"
|
||||
#include <curl/curl.h>
|
||||
|
||||
static constexpr char log_category_prefix[] = "JSONRPCRequest ";
|
||||
LOG_CATEGORY(JSONRPCRequest)
|
||||
|
||||
namespace p2pool {
|
||||
namespace JSONRPCRequest {
|
||||
@@ -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);
|
||||
|
||||
@@ -228,7 +230,9 @@ CurlContext::~CurlContext()
|
||||
double tcp_ping = 0.0;
|
||||
|
||||
if (m_error.empty() && !m_response.empty()) {
|
||||
tcp_ping = static_cast<double>(m_connectedTime - m_startTime) / 1000.0;
|
||||
if (m_connectedTime) {
|
||||
tcp_ping = static_cast<double>(m_connectedTime - m_startTime) / 1000.0;
|
||||
}
|
||||
(*m_callback)(m_response.data(), m_response.size(), tcp_ping);
|
||||
}
|
||||
delete m_callback;
|
||||
@@ -371,6 +375,10 @@ void CurlContext::on_timeout(uv_handle_t* req)
|
||||
|
||||
size_t CurlContext::on_write(const void* buffer, size_t size, size_t count)
|
||||
{
|
||||
if (!m_connectedTime) {
|
||||
m_connectedTime = microseconds_since_epoch();
|
||||
}
|
||||
|
||||
const size_t realsize = size * count;
|
||||
const char* p = reinterpret_cast<const char*>(buffer);
|
||||
m_response.insert(m_response.end(), p, p + realsize);
|
||||
|
||||
+5
-1
@@ -22,12 +22,14 @@
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
#include <stdlib.h>
|
||||
#include <clocale>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
static constexpr char log_category_prefix[] = "Log ";
|
||||
LOG_CATEGORY(Log)
|
||||
|
||||
static constexpr char log_file_name[] = "p2pool.log";
|
||||
|
||||
namespace p2pool {
|
||||
@@ -62,6 +64,8 @@ public:
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -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
|
||||
@@ -162,6 +170,7 @@ template<> struct Stream::Entry<const char*>
|
||||
|
||||
template<> struct Stream::Entry<char*>
|
||||
{
|
||||
// cppcheck-suppress constParameterPointer
|
||||
static FORCEINLINE void put(char* data, Stream* wrapper) { wrapper->writeBuf(data, strlen(data)); }
|
||||
};
|
||||
|
||||
@@ -287,7 +296,10 @@ template<> struct log::Stream::Entry<const_buf>
|
||||
|
||||
struct hex_buf
|
||||
{
|
||||
FORCEINLINE hex_buf(const uint8_t* data, size_t size) : m_data(data), m_size(size) {}
|
||||
FORCEINLINE hex_buf(const void* data, size_t size) : m_data(reinterpret_cast<const uint8_t*>(data)), m_size(size) {}
|
||||
|
||||
template<typename T>
|
||||
explicit FORCEINLINE hex_buf(const T* data) : m_data(reinterpret_cast<const uint8_t*>(data)), m_size(sizeof(T)) {}
|
||||
|
||||
const uint8_t* m_data;
|
||||
size_t m_size;
|
||||
@@ -506,17 +518,19 @@ struct DummyStream
|
||||
}
|
||||
#endif
|
||||
|
||||
#define LOG_CATEGORY(category) static constexpr char log_category_prefix[] = #category " ";
|
||||
|
||||
#ifdef P2POOL_LOG_DISABLE
|
||||
|
||||
#define LOGINFO(level, ...) SIDE_EFFECT_CHECK(level, __VA_ARGS__)
|
||||
#define LOGWARN(level, ...) SIDE_EFFECT_CHECK(level, __VA_ARGS__)
|
||||
#define LOGERR(level, ...) SIDE_EFFECT_CHECK(level, __VA_ARGS__)
|
||||
#define LOGINFO(level, ...) SIDE_EFFECT_CHECK(level, log_category_prefix << __VA_ARGS__)
|
||||
#define LOGWARN(level, ...) SIDE_EFFECT_CHECK(level, log_category_prefix << __VA_ARGS__)
|
||||
#define LOGERR(level, ...) SIDE_EFFECT_CHECK(level, log_category_prefix << __VA_ARGS__)
|
||||
|
||||
#else
|
||||
|
||||
#define LOG(level, severity, ...) \
|
||||
do { \
|
||||
SIDE_EFFECT_CHECK(level, __VA_ARGS__); \
|
||||
SIDE_EFFECT_CHECK(level, log_category_prefix << __VA_ARGS__); \
|
||||
if ((level) <= log::GLOBAL_LOG_LEVEL) { \
|
||||
log::Writer CONCAT(log_wrapper_, __LINE__)(severity); \
|
||||
CONCAT(log_wrapper_, __LINE__) << log::Gray() << log_category_prefix; \
|
||||
|
||||
+85
-3
@@ -22,6 +22,10 @@
|
||||
#include "p2p_server.h"
|
||||
#include <curl/curl.h>
|
||||
|
||||
#ifdef WITH_RANDOMX
|
||||
#include "randomx.h"
|
||||
#endif
|
||||
|
||||
void p2pool_usage()
|
||||
{
|
||||
printf("P2Pool %s\n"
|
||||
@@ -81,8 +85,80 @@ void p2pool_version()
|
||||
printf("P2Pool %s\n", p2pool::VERSION);
|
||||
}
|
||||
|
||||
void memory_tracking_start();
|
||||
void memory_tracking_stop();
|
||||
int p2pool_test()
|
||||
{
|
||||
#ifdef WITH_RANDOMX
|
||||
const char myKey[] = "test key 000";
|
||||
const char myInput[] = "This is a test";
|
||||
char hash[RANDOMX_HASH_SIZE];
|
||||
|
||||
const randomx_flags flags = randomx_get_flags() | RANDOMX_FLAG_FULL_MEM;
|
||||
randomx_cache* myCache = randomx_alloc_cache(flags);
|
||||
if (!myCache) {
|
||||
printf("Cache allocation failed\n");
|
||||
return 1;
|
||||
}
|
||||
randomx_init_cache(myCache, myKey, sizeof(myKey) - 1);
|
||||
|
||||
randomx_dataset* myDataset = randomx_alloc_dataset(flags);
|
||||
if (!myDataset) {
|
||||
printf("Dataset allocation failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
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);
|
||||
if (!myMachine) {
|
||||
printf("Failed to create a virtual machine");
|
||||
return 1;
|
||||
}
|
||||
|
||||
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) << '\0';
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
randomx_destroy_vm(myMachine);
|
||||
randomx_release_dataset(myDataset);
|
||||
#endif
|
||||
|
||||
printf("Self-test passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
@@ -101,6 +177,10 @@ int main(int argc, char* argv[])
|
||||
p2pool_version();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[i], "--test")) {
|
||||
return p2pool_test();
|
||||
}
|
||||
}
|
||||
|
||||
memory_tracking_start();
|
||||
@@ -124,7 +204,9 @@ int main(int argc, char* argv[])
|
||||
|
||||
p2pool::destroy_crypto_cache();
|
||||
|
||||
memory_tracking_stop();
|
||||
if (!memory_tracking_stop()) {
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -18,11 +18,12 @@
|
||||
#include "common.h"
|
||||
|
||||
// Simple memory leak detector for Windows users, works best in RelWithDebInfo configuration.
|
||||
#if defined(_WIN32) && 0
|
||||
#if defined(_WIN32) && defined(DEV_TRACK_MEMORY)
|
||||
|
||||
#include "uv_util.h"
|
||||
#include <atomic>
|
||||
#include <type_traits>
|
||||
#include <iostream>
|
||||
|
||||
#include <DbgHelp.h>
|
||||
|
||||
@@ -87,7 +88,7 @@ uint32_t num_allocations = 0;
|
||||
uint64_t total_allocated = 0;
|
||||
uint32_t cur_allocation_index = 1;
|
||||
|
||||
void show_top_10()
|
||||
void show_top_10_allocations()
|
||||
{
|
||||
TrackedAllocation* buf = reinterpret_cast<TrackedAllocation*>(VirtualAlloc(nullptr, sizeof(TrackedAllocation) * N, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
|
||||
if (!buf) {
|
||||
@@ -122,7 +123,8 @@ void show_top_10()
|
||||
|
||||
std::sort(buf, end, [](const auto& a, const auto& b) { return a.allocated_size > b.allocated_size; });
|
||||
|
||||
printf("%I64u total bytes allocated\n", total_allocated);
|
||||
printf("%I64u total bytes allocated\n\n", total_allocated);
|
||||
printf("Top 10 allocations:\n\n");
|
||||
|
||||
for (TrackedAllocation* p = buf; (p < buf + 10) && (p < end); ++p) {
|
||||
printf("%I64u bytes allocated at:\n", p->allocated_size);
|
||||
@@ -130,6 +132,8 @@ void show_top_10()
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
VirtualFree(buf, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
@@ -263,6 +267,9 @@ void* calloc_hook(size_t count, size_t size) noexcept
|
||||
|
||||
void memory_tracking_start()
|
||||
{
|
||||
// Trigger std::ostream initialization to avoid reporting it as leaks
|
||||
std::cout << "Memory leak detection = " << 1 << std::endl;
|
||||
|
||||
SymInitialize(GetCurrentProcess(), NULL, TRUE);
|
||||
|
||||
using namespace p2pool;
|
||||
@@ -272,7 +279,7 @@ void memory_tracking_start()
|
||||
track_memory = true;
|
||||
}
|
||||
|
||||
void memory_tracking_stop()
|
||||
bool memory_tracking_stop()
|
||||
{
|
||||
using namespace p2pool;
|
||||
|
||||
@@ -296,8 +303,13 @@ void memory_tracking_stop()
|
||||
if (total_leaks > 0) {
|
||||
printf("%I64u bytes leaked\n\n", total_leaks);
|
||||
}
|
||||
else {
|
||||
printf("No memory leaks detected\n\n");
|
||||
}
|
||||
|
||||
SymCleanup(h);
|
||||
|
||||
return (total_leaks == 0);
|
||||
}
|
||||
|
||||
NOINLINE void* operator new(size_t n) { return p2pool::allocate(n); }
|
||||
@@ -313,7 +325,7 @@ NOINLINE void operator delete[](void* p, size_t) noexcept { p2pool::free_hook(p)
|
||||
// cppcheck-suppress functionStatic
|
||||
void memory_tracking_start() {}
|
||||
// cppcheck-suppress functionStatic
|
||||
void memory_tracking_stop() {}
|
||||
bool memory_tracking_stop() { return true; }
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
#include "mempool.h"
|
||||
#include "util.h"
|
||||
|
||||
static constexpr char log_category_prefix[] = "Mempool ";
|
||||
LOG_CATEGORY(Mempool)
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
|
||||
+13
-4
@@ -28,7 +28,7 @@
|
||||
#include "p2p_server.h"
|
||||
#include <thread>
|
||||
|
||||
static constexpr char log_category_prefix[] = "Miner ";
|
||||
LOG_CATEGORY(Miner)
|
||||
|
||||
using namespace std::chrono;
|
||||
|
||||
@@ -85,11 +85,11 @@ void Miner::print_status()
|
||||
const uint64_t hr = (dt > 0.0) ? static_cast<uint64_t>(hash_count / dt) : 0;
|
||||
|
||||
char shares_failed_buf[64] = {};
|
||||
log::Stream s(shares_failed_buf);
|
||||
|
||||
const uint32_t shares_found = m_sharesFound;
|
||||
const uint32_t shares_failed = m_sharesFailed;
|
||||
if (shares_failed) {
|
||||
log::Stream s(shares_failed_buf);
|
||||
s << log::Yellow() << "\nShares failed = " << shares_failed << log::NoColor();
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
@@ -224,7 +224,16 @@ void Miner::run(WorkerData* data)
|
||||
job[index].set_nonce(static_cast<uint32_t>(full_nonce), static_cast<uint32_t>(full_nonce >> 32));
|
||||
|
||||
hash h;
|
||||
randomx_calculate_hash_next(vm, job[index].m_blob, job[index].m_blobSize, &h);
|
||||
try {
|
||||
randomx_calculate_hash_next(vm, job[index].m_blob, job[index].m_blobSize, &h);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
LOGERR(0, "Failed to calculate RandomX hash: exception \"" << e.what() << "\". Is your CPU/RAM unstable?" <<
|
||||
"\nFailed RandomX hash input: " << log::hex_buf(j.m_blob, j.m_blobSize));
|
||||
|
||||
// Make the result hash all FF's to fail difficulty checks
|
||||
memset(h.h, -1, HASH_SIZE);
|
||||
}
|
||||
|
||||
if (j.m_diff.check_pow(h)) {
|
||||
LOGINFO(0, log::Green() << "worker thread " << data->m_index << '/' << data->m_count << " found a mainchain block at height " << j.m_height << ", submitting it");
|
||||
|
||||
+311
-101
@@ -31,10 +31,11 @@
|
||||
#include <fstream>
|
||||
#include <numeric>
|
||||
|
||||
static constexpr char log_category_prefix[] = "P2PServer ";
|
||||
LOG_CATEGORY(P2PServer)
|
||||
|
||||
static constexpr char saved_peer_list_file_name[] = "p2pool_peers.txt";
|
||||
static const char* seed_nodes[] = { "seeds.p2pool.io", ""};
|
||||
static const char* seed_nodes_mini[] = { "seeds-mini.p2pool.io", "" };
|
||||
static const char* seed_nodes[] = { "seeds.p2pool.io", "main.p2poolpeers.net", ""};
|
||||
static const char* seed_nodes_mini[] = { "seeds-mini.p2pool.io", "mini.p2poolpeers.net", "" };
|
||||
|
||||
static constexpr int DEFAULT_BACKLOG = 16;
|
||||
static constexpr uint64_t DEFAULT_BAN_TIME = 600;
|
||||
@@ -58,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);
|
||||
@@ -90,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) {
|
||||
@@ -148,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;
|
||||
@@ -204,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);
|
||||
@@ -268,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);
|
||||
@@ -301,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);
|
||||
@@ -459,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';
|
||||
@@ -593,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;
|
||||
}
|
||||
@@ -698,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;
|
||||
@@ -709,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -740,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();
|
||||
@@ -826,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -883,12 +900,28 @@ void P2PServer::on_broadcast()
|
||||
{
|
||||
uint8_t* p = buf;
|
||||
|
||||
bool send_pruned = true;
|
||||
bool send_compact = (client->m_protocolVersion >= PROTOCOL_VERSION_1_1) && !data->compact_blob.empty() && (data->compact_blob.size() < data->pruned_blob.size());
|
||||
|
||||
const hash* a = client->m_broadcastedHashes;
|
||||
const hash* b = client->m_broadcastedHashes + array_size(&P2PClient::m_broadcastedHashes);
|
||||
|
||||
// If this peer already broadcasted this block to us, we don't need to broadcast it back, we just need to notify the peer
|
||||
if ((client->m_protocolVersion >= PROTOCOL_VERSION_1_2) && (std::find(a, b, data->id) != b)) {
|
||||
LOGINFO(6, "sending BLOCK_NOTIFY to " << log::Gray() << static_cast<char*>(client->m_addrString));
|
||||
|
||||
if (buf_size < 1 + HASH_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*(p++) = static_cast<uint8_t>(MessageId::BLOCK_NOTIFY);
|
||||
|
||||
memcpy(p, data->id.h, HASH_SIZE);
|
||||
p += HASH_SIZE;
|
||||
|
||||
return p - buf;
|
||||
}
|
||||
|
||||
bool send_pruned = true;
|
||||
bool send_compact = (client->m_protocolVersion >= PROTOCOL_VERSION_1_1) && !data->compact_blob.empty() && (data->compact_blob.size() < data->pruned_blob.size());
|
||||
|
||||
for (const hash& id : data->ancestor_hashes) {
|
||||
if (std::find(a, b, id) == b) {
|
||||
send_pruned = false;
|
||||
@@ -898,7 +931,7 @@ void P2PServer::on_broadcast()
|
||||
}
|
||||
|
||||
if (send_pruned) {
|
||||
LOGINFO(6, "sending BLOCK_BROADCAST (" << (send_compact ? "compact" : "pruned") << ") to " << log::Gray() << static_cast<char*>(client->m_addrString));
|
||||
LOGINFO(6, "sending BLOCK_BROADCAST " << (send_compact ? "(compact)" : "(pruned) ") << " to " << log::Gray() << static_cast<char*>(client->m_addrString));
|
||||
const std::vector<uint8_t>& blob = send_compact ? data->compact_blob : data->pruned_blob;
|
||||
|
||||
const uint32_t len = static_cast<uint32_t>(blob.size());
|
||||
@@ -917,7 +950,7 @@ void P2PServer::on_broadcast()
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOGINFO(5, "sending BLOCK_BROADCAST (full) to " << log::Gray() << static_cast<char*>(client->m_addrString));
|
||||
LOGINFO(5, "sending BLOCK_BROADCAST (full) to " << log::Gray() << static_cast<char*>(client->m_addrString));
|
||||
|
||||
const uint32_t len = static_cast<uint32_t>(data->blob.size());
|
||||
if (buf_size < 1 + sizeof(uint32_t) + len) {
|
||||
@@ -971,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);
|
||||
}
|
||||
@@ -986,8 +1021,8 @@ void P2PServer::show_peers() const
|
||||
for (P2PClient* client = static_cast<P2PClient*>(m_connectedClientsList->m_next); client != m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
|
||||
if (client->m_listenPort >= 0) {
|
||||
char buf[32] = {};
|
||||
log::Stream s(buf);
|
||||
if (client->m_SoftwareVersion) {
|
||||
log::Stream s(buf);
|
||||
s << client->software_name() << " v" << (client->m_SoftwareVersion >> 16) << '.' << (client->m_SoftwareVersion & 0xFFFF);
|
||||
}
|
||||
LOGINFO(0, (client->m_isIncoming ? "I\t" : "O\t")
|
||||
@@ -1028,6 +1063,16 @@ int P2PServer::deserialize_block(const uint8_t* buf, uint32_t size, bool compact
|
||||
return result;
|
||||
}
|
||||
|
||||
const PoolBlock* P2PServer::find_block(const hash& id) const
|
||||
{
|
||||
return m_pool->side_chain().find_block(id);
|
||||
}
|
||||
|
||||
const char* P2PServer::get_log_category() const
|
||||
{
|
||||
return log_category_prefix;
|
||||
}
|
||||
|
||||
void P2PServer::on_timer()
|
||||
{
|
||||
if (m_pool->stopped()) {
|
||||
@@ -1048,6 +1093,7 @@ void P2PServer::on_timer()
|
||||
update_peer_connections();
|
||||
check_host();
|
||||
check_block_template();
|
||||
check_for_updates();
|
||||
api_update_local_stats();
|
||||
}
|
||||
|
||||
@@ -1093,12 +1139,13 @@ void P2PServer::download_missing_blocks()
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<hash> missing_blocks;
|
||||
unordered_set<hash> missing_blocks;
|
||||
m_pool->side_chain().get_missing_blocks(missing_blocks);
|
||||
|
||||
if (missing_blocks.empty()) {
|
||||
m_lookForMissingBlocks = false;
|
||||
m_missingBlockRequests.clear();
|
||||
m_blockNotifyRequests.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1125,8 +1172,12 @@ void P2PServer::download_missing_blocks()
|
||||
for (const hash& id : missing_blocks) {
|
||||
P2PClient* client = clients[get_random64() % clients.size()];
|
||||
|
||||
const uint64_t truncated_block_id = *reinterpret_cast<const uint64_t*>(id.h);
|
||||
if (!m_missingBlockRequests.insert({ client->m_peerId, truncated_block_id }).second) {
|
||||
if (client->m_blockPendingRequests.size() >= 25) {
|
||||
// Too many pending requests to this peer
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!m_missingBlockRequests.emplace(client->m_peerId, *id.u64()).second) {
|
||||
// We already asked this peer about this block
|
||||
// Don't try to ask another peer, leave it for another timer tick
|
||||
continue;
|
||||
@@ -1144,7 +1195,7 @@ void P2PServer::download_missing_blocks()
|
||||
const bool result = send(client,
|
||||
[&id, client](uint8_t* buf, size_t buf_size) -> size_t
|
||||
{
|
||||
LOGINFO(5, "sending BLOCK_REQUEST for id = " << id << " to " << static_cast<char*>(client->m_addrString));
|
||||
LOGINFO(5, "[download_missing_blocks] sending BLOCK_REQUEST for id = " << id << " to " << static_cast<char*>(client->m_addrString));
|
||||
|
||||
if (buf_size < 1 + HASH_SIZE) {
|
||||
return 0;
|
||||
@@ -1161,7 +1212,7 @@ void P2PServer::download_missing_blocks()
|
||||
});
|
||||
|
||||
if (result) {
|
||||
client->m_blockPendingRequests.push_back(id);
|
||||
client->m_blockPendingRequests.push_back(*id.u64());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1186,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;
|
||||
}
|
||||
@@ -1199,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();
|
||||
}
|
||||
}
|
||||
@@ -1217,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)
|
||||
@@ -1234,12 +1306,13 @@ 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)
|
||||
, m_lastBlockrequestTimestamp(0)
|
||||
, m_broadcastedHashes{}
|
||||
, m_broadcastedHashesIndex(0)
|
||||
{
|
||||
m_p2pReadBuf[0] = '\0';
|
||||
}
|
||||
@@ -1250,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;
|
||||
}
|
||||
|
||||
@@ -1266,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;
|
||||
@@ -1294,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;
|
||||
}
|
||||
}
|
||||
@@ -1335,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;
|
||||
@@ -1401,7 +1485,14 @@ bool P2PServer::P2PClient::on_read(char* data, uint32_t size)
|
||||
|
||||
uint32_t bytes_read;
|
||||
do {
|
||||
MessageId id = static_cast<MessageId>(buf[0]);
|
||||
if (buf[0] > static_cast<uint8_t>(MessageId::LAST)) {
|
||||
LOGWARN(5, "peer " << static_cast<char*>(m_addrString) << " sent an unknown message id " << buf[0]);
|
||||
ban(DEFAULT_BAN_TIME);
|
||||
server->remove_peer_from_list(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
const MessageId id = static_cast<MessageId>(buf[0]);
|
||||
|
||||
// Peer must complete the handshake challenge before sending any other messages
|
||||
if (!m_handshakeComplete && (id != m_expectedMessage)) {
|
||||
@@ -1511,7 +1602,7 @@ bool P2PServer::P2PClient::on_read(char* data, uint32_t size)
|
||||
if (bytes_left >= 1 + sizeof(uint32_t) + block_size) {
|
||||
bytes_read = 1 + sizeof(uint32_t) + block_size;
|
||||
|
||||
const hash expected_id = m_blockPendingRequests.front();
|
||||
const uint64_t expected_id = m_blockPendingRequests.front();
|
||||
m_blockPendingRequests.pop_front();
|
||||
|
||||
if (!on_block_response(buf + 1 + sizeof(uint32_t), block_size, expected_id)) {
|
||||
@@ -1586,6 +1677,15 @@ bool P2PServer::P2PClient::on_read(char* data, uint32_t size)
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MessageId::BLOCK_NOTIFY:
|
||||
LOGINFO(6, "peer " << log::Gray() << static_cast<char*>(m_addrString) << log::NoColor() << " sent BLOCK_NOTIFY");
|
||||
|
||||
if (bytes_left >= 1 + HASH_SIZE) {
|
||||
bytes_read = 1 + HASH_SIZE;
|
||||
on_block_notify(buf + 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (bytes_read) {
|
||||
@@ -1732,7 +1832,7 @@ void P2PServer::P2PClient::send_handshake_solution(const uint8_t (&challenge)[CH
|
||||
return;
|
||||
}
|
||||
|
||||
const uint64_t* value = reinterpret_cast<uint64_t*>(work->solution.h);
|
||||
const uint64_t* value = work->solution.u64();
|
||||
|
||||
uint64_t high;
|
||||
umul128(value[HASH_SIZE / sizeof(uint64_t) - 1], CHALLENGE_DIFFICULTY, &high);
|
||||
@@ -1878,7 +1978,7 @@ bool P2PServer::P2PClient::on_handshake_solution(const uint8_t* buf)
|
||||
|
||||
// Check that incoming connection provided enough PoW
|
||||
if (m_isIncoming) {
|
||||
const uint64_t* value = reinterpret_cast<uint64_t*>(solution.h);
|
||||
const uint64_t* value = solution.u64();
|
||||
|
||||
uint64_t high;
|
||||
umul128(value[HASH_SIZE / sizeof(uint64_t) - 1], CHALLENGE_DIFFICULTY, &high);
|
||||
@@ -1939,7 +2039,7 @@ void P2PServer::P2PClient::on_after_handshake(uint8_t* &p)
|
||||
memcpy(p, zero_hash.h, HASH_SIZE);
|
||||
p += HASH_SIZE;
|
||||
|
||||
m_blockPendingRequests.push_back(zero_hash);
|
||||
m_blockPendingRequests.push_back(0);
|
||||
m_lastBroadcastTimestamp = seconds_since_epoch();
|
||||
}
|
||||
|
||||
@@ -1967,14 +2067,32 @@ bool P2PServer::P2PClient::on_block_request(const uint8_t* buf)
|
||||
memcpy(id.h, buf, HASH_SIZE);
|
||||
|
||||
P2PServer* server = static_cast<P2PServer*>(m_owner);
|
||||
const SideChain& sidechain = server->m_pool->side_chain();
|
||||
|
||||
std::vector<uint8_t> blob;
|
||||
if (!server->m_pool->side_chain().get_block_blob(id, blob) && !id.empty()) {
|
||||
const PoolBlock* block = sidechain.get_block_blob(id, blob);
|
||||
|
||||
if (!block && !id.empty()) {
|
||||
LOGWARN(5, "got a request for block with id " << id << " but couldn't find it");
|
||||
}
|
||||
|
||||
// Notifications about parent and uncle blocks to speed up syncing
|
||||
std::vector<hash> notify_blocks;
|
||||
|
||||
if (block && (m_protocolVersion >= PROTOCOL_VERSION_1_2)) {
|
||||
notify_blocks.reserve(block->m_uncles.size() + 2);
|
||||
|
||||
notify_blocks.push_back(block->m_parent);
|
||||
notify_blocks.insert(notify_blocks.end(), block->m_uncles.begin(), block->m_uncles.end());
|
||||
|
||||
block = sidechain.find_block(block->m_parent);
|
||||
if (block) {
|
||||
notify_blocks.push_back(block->m_parent);
|
||||
}
|
||||
}
|
||||
|
||||
return server->send(this,
|
||||
[this, &blob](uint8_t* buf, size_t buf_size) -> size_t
|
||||
[this, &blob, ¬ify_blocks](uint8_t* buf, size_t buf_size) -> size_t
|
||||
{
|
||||
LOGINFO(5, "sending BLOCK_RESPONSE to " << static_cast<char*>(m_addrString));
|
||||
|
||||
@@ -1986,6 +2104,17 @@ bool P2PServer::P2PClient::on_block_request(const uint8_t* buf)
|
||||
|
||||
uint8_t* p = buf;
|
||||
|
||||
if (buf_size >= 1 + sizeof(uint32_t) + len + notify_blocks.size() * (1 + HASH_SIZE)) {
|
||||
for (const hash& id : notify_blocks) {
|
||||
LOGINFO(6, "sending BLOCK_NOTIFY for " << id << " to " << static_cast<char*>(m_addrString));
|
||||
|
||||
*(p++) = static_cast<uint8_t>(MessageId::BLOCK_NOTIFY);
|
||||
|
||||
memcpy(p, id.h, HASH_SIZE);
|
||||
p += HASH_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
*(p++) = static_cast<uint8_t>(MessageId::BLOCK_RESPONSE);
|
||||
|
||||
memcpy(p, &len, sizeof(uint32_t));
|
||||
@@ -2000,14 +2129,14 @@ bool P2PServer::P2PClient::on_block_request(const uint8_t* buf)
|
||||
});
|
||||
}
|
||||
|
||||
bool P2PServer::P2PClient::on_block_response(const uint8_t* buf, uint32_t size, const hash& expected_id)
|
||||
bool P2PServer::P2PClient::on_block_response(const uint8_t* buf, uint32_t size, uint64_t expected_id)
|
||||
{
|
||||
P2PServer* server = static_cast<P2PServer*>(m_owner);
|
||||
const uint64_t cur_time = seconds_since_epoch();
|
||||
|
||||
if (!size) {
|
||||
LOGINFO(5, "peer " << log::Gray() << static_cast<char*>(m_addrString) << log::NoColor() << " sent an empty block response");
|
||||
if (expected_id.empty() && (cur_time >= m_nextOutgoingPeerListRequest)) {
|
||||
if ((expected_id == 0) && (cur_time >= m_nextOutgoingPeerListRequest)) {
|
||||
server->send_peer_list_request(this, cur_time);
|
||||
}
|
||||
return true;
|
||||
@@ -2026,7 +2155,7 @@ bool P2PServer::P2PClient::on_block_response(const uint8_t* buf, uint32_t size,
|
||||
const PoolBlock* block = server->get_block();
|
||||
|
||||
// Chain tip request
|
||||
if (expected_id.empty()) {
|
||||
if (expected_id == 0) {
|
||||
const uint64_t peer_height = block->m_txinGenHeight;
|
||||
const uint64_t our_height = server->m_pool->miner_data().height;
|
||||
|
||||
@@ -2035,12 +2164,15 @@ bool P2PServer::P2PClient::on_block_response(const uint8_t* buf, uint32_t size,
|
||||
return false;
|
||||
}
|
||||
|
||||
m_broadcastMaxHeight = std::max(m_broadcastMaxHeight, block->m_sidechainHeight);
|
||||
m_broadcastedHashes[m_broadcastedHashesIndex++ % array_size(&P2PClient::m_broadcastedHashes)] = block->m_sidechainId;
|
||||
|
||||
if (cur_time >= m_nextOutgoingPeerListRequest) {
|
||||
server->send_peer_list_request(this, cur_time);
|
||||
}
|
||||
}
|
||||
else if (block->m_sidechainId != expected_id) {
|
||||
LOGWARN(3, "peer " << static_cast<char*>(m_addrString) << " sent a wrong block: expected " << expected_id << ", got " << block->m_sidechainId);
|
||||
else if (*block->m_sidechainId.u64() != expected_id) {
|
||||
LOGWARN(3, "peer " << static_cast<char*>(m_addrString) << " sent a wrong block: expected " << log::hex_buf(&expected_id) << ", got " << block->m_sidechainId);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2072,7 +2204,7 @@ bool P2PServer::P2PClient::on_block_broadcast(const uint8_t* buf, uint32_t size,
|
||||
const PoolBlock* block = server->get_block();
|
||||
|
||||
m_broadcastMaxHeight = std::max(m_broadcastMaxHeight, block->m_sidechainHeight);
|
||||
m_broadcastedHashes[m_broadcastedHashesIndex.fetch_add(1) % array_size(&P2PClient::m_broadcastedHashes)] = block->m_sidechainId;
|
||||
m_broadcastedHashes[m_broadcastedHashesIndex++ % array_size(&P2PClient::m_broadcastedHashes)] = block->m_sidechainId;
|
||||
|
||||
MinerData miner_data = server->m_pool->miner_data();
|
||||
|
||||
@@ -2167,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) {
|
||||
@@ -2236,27 +2369,43 @@ 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)) {
|
||||
m_protocolVersion = *reinterpret_cast<uint32_t*>(ip.data);
|
||||
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
|
||||
// to reduce backwards compatibility requirements for newer clients
|
||||
if ((version >> 16) != (SUPPORTED_PROTOCOL_VERSION >> 16)) {
|
||||
m_protocolVersion = PROTOCOL_VERSION_1_0;
|
||||
}
|
||||
else {
|
||||
m_protocolVersion = std::min(version, SUPPORTED_PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
m_SoftwareVersion = *reinterpret_cast<uint32_t*>(ip.data + 4);
|
||||
m_SoftwareID = *reinterpret_cast<uint32_t*>(ip.data + 8);
|
||||
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;
|
||||
@@ -2264,7 +2413,57 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void P2PServer::P2PClient::on_block_notify(const uint8_t* buf)
|
||||
{
|
||||
hash id;
|
||||
memcpy(id.h, buf, HASH_SIZE);
|
||||
|
||||
m_broadcastedHashes[m_broadcastedHashesIndex++ % array_size(&P2PClient::m_broadcastedHashes)] = id;
|
||||
|
||||
P2PServer* server = static_cast<P2PServer*>(m_owner);
|
||||
|
||||
// If we don't know about this block, request it from this peer. The peer can do it to speed up our initial sync, for example.
|
||||
if (!server->find_block(id)) {
|
||||
LOGINFO(6, "Received an unknown block " << id << " in BLOCK_NOTIFY");
|
||||
|
||||
if (m_blockPendingRequests.size() >= 25) {
|
||||
LOGINFO(5, "Too many pending block requests, ignoring it");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!server->m_blockNotifyRequests.insert(*id.u64()).second || !server->m_missingBlockRequests.emplace(m_peerId, *id.u64()).second) {
|
||||
LOGINFO(6, "BLOCK_REQUEST for id = " << id << " was already sent");
|
||||
return;
|
||||
}
|
||||
|
||||
const bool result = server->send(this,
|
||||
[&id, this](uint8_t* buf, size_t buf_size) -> size_t
|
||||
{
|
||||
LOGINFO(5, "[on_block_notify] sending BLOCK_REQUEST for id = " << id << " to " << static_cast<char*>(m_addrString));
|
||||
|
||||
if (buf_size < 1 + HASH_SIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t* p = buf;
|
||||
|
||||
*(p++) = static_cast<uint8_t>(MessageId::BLOCK_REQUEST);
|
||||
|
||||
memcpy(p, id.h, HASH_SIZE);
|
||||
p += HASH_SIZE;
|
||||
|
||||
return p - buf;
|
||||
});
|
||||
|
||||
if (result) {
|
||||
m_blockPendingRequests.push_back(*id.u64());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2335,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,
|
||||
@@ -2345,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->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);
|
||||
});
|
||||
@@ -2364,30 +2564,33 @@ 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");
|
||||
}
|
||||
else {
|
||||
const log::hex_buf addr_hex(addr.data, sizeof(addr.data));
|
||||
LOGWARN(3, "IP " << addr_hex << " banned for " << DEFAULT_BAN_TIME << " seconds");
|
||||
LOGWARN(3, addr << " banned for " << DEFAULT_BAN_TIME << " seconds");
|
||||
}
|
||||
|
||||
P2PServer* server = pool->p2p_server();
|
||||
server->ban(is_v6, addr, DEFAULT_BAN_TIME);
|
||||
server->remove_peer_from_list(addr);
|
||||
}
|
||||
}
|
||||
|
||||
void P2PServer::P2PClient::post_handle_incoming_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;
|
||||
}
|
||||
|
||||
@@ -2397,11 +2600,14 @@ void P2PServer::P2PClient::post_handle_incoming_block(const uint32_t reset_count
|
||||
|
||||
P2PServer* server = static_cast<P2PServer*>(m_owner);
|
||||
|
||||
// If the initial sync is not finished yet, try to ask the fastest peer too
|
||||
P2PClient* c = server->m_fastestPeer;
|
||||
if (c && (c != this) && !server->m_pool->side_chain().precalcFinished()) {
|
||||
LOGINFO(5, "peer " << static_cast<char*>(c->m_addrString) << " is faster, sending BLOCK_REQUEST to it too");
|
||||
c->post_handle_incoming_block(c->m_resetCounter.load(), missing_blocks);
|
||||
// If the initial sync is not finished yet, try to ask the fastest peer instead
|
||||
if (!server->m_pool->side_chain().precalcFinished()) {
|
||||
P2PClient* c = server->m_fastestPeer;
|
||||
if (c && (c != this) && (c->m_broadcastMaxHeight >= block.m_sidechainHeight)) {
|
||||
LOGINFO(5, "peer " << static_cast<char*>(c->m_addrString) << " is faster, sending BLOCK_REQUEST to it instead");
|
||||
c->post_handle_incoming_block(pool, block, c->m_resetCounter.load(), c->m_isV6, c->m_addr, missing_blocks, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ReadLock lock(server->m_cachedBlocksLock);
|
||||
@@ -2416,10 +2622,14 @@ void P2PServer::P2PClient::post_handle_incoming_block(const uint32_t reset_count
|
||||
}
|
||||
}
|
||||
|
||||
const bool result = server->send(this,
|
||||
if (!server->m_missingBlockRequests.emplace(m_peerId, *id.u64()).second) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool send_result = server->send(this,
|
||||
[this, &id](uint8_t* buf, size_t buf_size) -> size_t
|
||||
{
|
||||
LOGINFO(5, "sending BLOCK_REQUEST for id = " << id << " to " << static_cast<char*>(m_addrString));
|
||||
LOGINFO(5, "[post_handle_incoming_block] sending BLOCK_REQUEST for id = " << id << " to " << static_cast<char*>(m_addrString));
|
||||
|
||||
if (buf_size < 1 + HASH_SIZE) {
|
||||
return 0;
|
||||
@@ -2435,20 +2645,20 @@ void P2PServer::P2PClient::post_handle_incoming_block(const uint32_t reset_count
|
||||
return p - buf;
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
if (!send_result) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_blockPendingRequests.push_back(id);
|
||||
m_blockPendingRequests.push_back(*id.u64());
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
|
||||
+31
-18
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "tcp_server.h"
|
||||
#include "pool_block.h"
|
||||
#include <list>
|
||||
#include <deque>
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
@@ -37,22 +37,25 @@ static constexpr int DEFAULT_P2P_PORT_MINI = 37888;
|
||||
|
||||
static constexpr uint32_t PROTOCOL_VERSION_1_0 = 0x00010000UL;
|
||||
static constexpr uint32_t PROTOCOL_VERSION_1_1 = 0x00010001UL;
|
||||
static constexpr uint32_t PROTOCOL_VERSION_1_2 = 0x00010002UL;
|
||||
|
||||
static constexpr uint32_t SUPPORTED_PROTOCOL_VERSION = PROTOCOL_VERSION_1_1;
|
||||
static constexpr uint32_t SUPPORTED_PROTOCOL_VERSION = PROTOCOL_VERSION_1_2;
|
||||
|
||||
class P2PServer : public TCPServer
|
||||
{
|
||||
public:
|
||||
enum class MessageId {
|
||||
HANDSHAKE_CHALLENGE = 0,
|
||||
HANDSHAKE_SOLUTION = 1,
|
||||
LISTEN_PORT = 2,
|
||||
BLOCK_REQUEST = 3,
|
||||
BLOCK_RESPONSE = 4,
|
||||
BLOCK_BROADCAST = 5,
|
||||
PEER_LIST_REQUEST = 6,
|
||||
PEER_LIST_RESPONSE = 7,
|
||||
BLOCK_BROADCAST_COMPACT = 8,
|
||||
HANDSHAKE_CHALLENGE,
|
||||
HANDSHAKE_SOLUTION,
|
||||
LISTEN_PORT,
|
||||
BLOCK_REQUEST,
|
||||
BLOCK_RESPONSE,
|
||||
BLOCK_BROADCAST,
|
||||
PEER_LIST_REQUEST,
|
||||
PEER_LIST_RESPONSE,
|
||||
BLOCK_BROADCAST_COMPACT,
|
||||
BLOCK_NOTIFY,
|
||||
LAST = BLOCK_NOTIFY,
|
||||
};
|
||||
|
||||
explicit P2PServer(p2pool *pool);
|
||||
@@ -105,14 +108,15 @@ public:
|
||||
void on_after_handshake(uint8_t* &p);
|
||||
bool on_listen_port(const uint8_t* buf);
|
||||
bool on_block_request(const uint8_t* buf);
|
||||
bool on_block_response(const uint8_t* buf, uint32_t size, const hash& expected_id);
|
||||
bool on_block_response(const uint8_t* buf, uint32_t size, uint64_t expected_id);
|
||||
bool on_block_broadcast(const uint8_t* buf, uint32_t size, bool compact);
|
||||
bool on_peer_list_request(const uint8_t* buf);
|
||||
void on_peer_list_response(const uint8_t* buf);
|
||||
void on_block_notify(const uint8_t* buf);
|
||||
|
||||
bool handle_incoming_block_async(const PoolBlock* block, uint64_t max_time_delta = 0);
|
||||
void handle_incoming_block(p2pool* pool, PoolBlock& block, const uint32_t reset_counter, bool is_v6, const raw_ip& addr, std::vector<hash>& missing_blocks);
|
||||
void post_handle_incoming_block(const uint32_t reset_counter, std::vector<hash>& missing_blocks);
|
||||
void 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); }
|
||||
|
||||
@@ -138,18 +142,18 @@ public:
|
||||
|
||||
uint32_t m_protocolVersion;
|
||||
uint32_t m_SoftwareVersion;
|
||||
uint32_t m_SoftwareID;
|
||||
SoftwareID m_SoftwareID;
|
||||
|
||||
int64_t m_pingTime;
|
||||
|
||||
std::list<hash> m_blockPendingRequests;
|
||||
std::deque<uint64_t> m_blockPendingRequests;
|
||||
|
||||
uint64_t m_lastAlive;
|
||||
uint64_t m_lastBroadcastTimestamp;
|
||||
uint64_t m_lastBlockrequestTimestamp;
|
||||
|
||||
hash m_broadcastedHashes[8];
|
||||
std::atomic<uint32_t> m_broadcastedHashesIndex{ 0 };
|
||||
uint32_t m_broadcastedHashesIndex;
|
||||
};
|
||||
|
||||
void broadcast(const PoolBlock& block, const PoolBlock* parent);
|
||||
@@ -171,8 +175,12 @@ public:
|
||||
int deserialize_block(const uint8_t* buf, uint32_t size, bool compact, uint64_t received_timestamp);
|
||||
const PoolBlock* get_block() const { return m_block; }
|
||||
|
||||
const PoolBlock* find_block(const hash& id) const;
|
||||
|
||||
void check_for_updates(bool forced = false) const;
|
||||
|
||||
private:
|
||||
const char* get_category() const override { return "P2PServer "; }
|
||||
const char* get_log_category() const override;
|
||||
|
||||
p2pool* m_pool;
|
||||
BlockCache* m_cache;
|
||||
@@ -220,6 +228,8 @@ private:
|
||||
|
||||
struct Peer
|
||||
{
|
||||
void normalize();
|
||||
|
||||
bool m_isV6;
|
||||
raw_ip m_addr;
|
||||
int m_port;
|
||||
@@ -248,8 +258,10 @@ private:
|
||||
|
||||
bool m_lookForMissingBlocks;
|
||||
unordered_set<std::pair<uint64_t, uint64_t>> m_missingBlockRequests;
|
||||
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();
|
||||
@@ -260,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(); }
|
||||
|
||||
+10
-10
@@ -40,7 +40,8 @@
|
||||
#include <fstream>
|
||||
#include <numeric>
|
||||
|
||||
constexpr char log_category_prefix[] = "P2Pool ";
|
||||
LOG_CATEGORY(P2Pool)
|
||||
|
||||
constexpr int BLOCK_HEADERS_REQUIRED = 720;
|
||||
|
||||
constexpr uint64_t SEEDHASH_EPOCH_BLOCKS = 2048;
|
||||
@@ -912,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();
|
||||
@@ -924,7 +925,7 @@ void p2pool::get_info()
|
||||
|
||||
void p2pool::load_found_blocks()
|
||||
{
|
||||
if (!m_api) {
|
||||
if (!m_api || m_stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1106,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;
|
||||
@@ -1276,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;
|
||||
}
|
||||
|
||||
@@ -1307,7 +1308,7 @@ void p2pool::api_update_network_stats()
|
||||
|
||||
void p2pool::api_update_pool_stats()
|
||||
{
|
||||
if (!m_api) {
|
||||
if (!m_api || m_stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1359,7 +1360,7 @@ void p2pool::api_update_pool_stats()
|
||||
|
||||
void p2pool::api_update_stats_mod()
|
||||
{
|
||||
if (!m_api) {
|
||||
if (!m_api || m_stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1452,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;
|
||||
}
|
||||
|
||||
@@ -1690,8 +1691,7 @@ int p2pool::run()
|
||||
m_ZMQReader = nullptr;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
const char* s = e.what();
|
||||
LOGERR(1, "exception " << s);
|
||||
LOGERR(1, "exception " << e.what());
|
||||
PANIC_STOP();
|
||||
}
|
||||
|
||||
|
||||
+14
-6
@@ -24,7 +24,7 @@
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
static constexpr char log_category_prefix[] = "P2Pool API ";
|
||||
LOG_CATEGORY(P2Pool API)
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
@@ -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);
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
#include "stratum_server.h"
|
||||
#include "p2p_server.h"
|
||||
|
||||
constexpr char log_category_prefix[] = "P2Pool ";
|
||||
LOG_CATEGORY(Params)
|
||||
|
||||
void p2pool_usage();
|
||||
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@
|
||||
#include "pow_hash.h"
|
||||
#include "crypto.h"
|
||||
|
||||
static constexpr char log_category_prefix[] = "PoolBlock ";
|
||||
LOG_CATEGORY(PoolBlock)
|
||||
|
||||
#include "pool_block_parser.inl"
|
||||
|
||||
|
||||
@@ -393,8 +393,7 @@ int PoolBlock::deserialize(const uint8_t* data, size_t size, const SideChain& si
|
||||
}
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
const char* msg = e.what();
|
||||
LOGERR(0, "Exception in PoolBlock::deserialize(): " << (msg ? msg : "unknown exception"));
|
||||
LOGERR(0, "Exception in PoolBlock::deserialize(): " << e.what());
|
||||
return __LINE__;
|
||||
}
|
||||
|
||||
|
||||
+22
-12
@@ -29,7 +29,7 @@
|
||||
#include <rapidjson/document.h>
|
||||
#include <thread>
|
||||
|
||||
static constexpr char log_category_prefix[] = "RandomX_Hasher ";
|
||||
LOG_CATEGORY(RandomX_Hasher)
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
@@ -322,6 +322,22 @@ void RandomX_Hasher::sync_wait()
|
||||
ReadLock lock2(m_cacheLock);
|
||||
}
|
||||
|
||||
static bool randomx_calculate_hash_safe(randomx_vm* machine, const void* input, size_t inputSize, void* output)
|
||||
{
|
||||
// Try to calculate the hash again if something went wrong the first time (for example, because of an unstable CPU)
|
||||
for (size_t i = 0; i < 2; ++i) {
|
||||
try {
|
||||
randomx_calculate_hash(machine, input, inputSize, output);
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
LOGERR(0, "Failed to calculate RandomX hash: exception \"" << e.what() << "\". Is your CPU/RAM unstable?" <<
|
||||
"\nFailed RandomX hash input: " << log::hex_buf(input, inputSize));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RandomX_Hasher::calculate(const void* data, size_t size, uint64_t /*height*/, const hash& seed, hash& result, bool force_light_mode)
|
||||
{
|
||||
// First try to use the dataset if it's ready
|
||||
@@ -335,8 +351,7 @@ bool RandomX_Hasher::calculate(const void* data, size_t size, uint64_t /*height*
|
||||
MutexLock lock(m_vm[FULL_DATASET_VM].mutex);
|
||||
|
||||
if (m_vm[FULL_DATASET_VM].vm && (seed == m_seed[m_index])) {
|
||||
randomx_calculate_hash(m_vm[FULL_DATASET_VM].vm, data, size, &result);
|
||||
return true;
|
||||
return randomx_calculate_hash_safe(m_vm[FULL_DATASET_VM].vm, data, size, &result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,8 +365,7 @@ bool RandomX_Hasher::calculate(const void* data, size_t size, uint64_t /*height*
|
||||
{
|
||||
MutexLock lock2(m_vm[m_index].mutex);
|
||||
if (m_vm[m_index].vm && (seed == m_seed[m_index])) {
|
||||
randomx_calculate_hash(m_vm[m_index].vm, data, size, &result);
|
||||
return true;
|
||||
return randomx_calculate_hash_safe(m_vm[m_index].vm, data, size, &result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,8 +374,7 @@ bool RandomX_Hasher::calculate(const void* data, size_t size, uint64_t /*height*
|
||||
MutexLock lock2(m_vm[prev_index].mutex);
|
||||
|
||||
if (m_vm[prev_index].vm && (seed == m_seed[prev_index])) {
|
||||
randomx_calculate_hash(m_vm[prev_index].vm, data, size, &result);
|
||||
return true;
|
||||
return randomx_calculate_hash_safe(m_vm[prev_index].vm, data, size, &result);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -383,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);
|
||||
@@ -443,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();
|
||||
@@ -472,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);
|
||||
}
|
||||
|
||||
+128
-42
@@ -40,7 +40,7 @@
|
||||
#include <iterator>
|
||||
#include <numeric>
|
||||
|
||||
static constexpr char log_category_prefix[] = "SideChain ";
|
||||
LOG_CATEGORY(SideChain)
|
||||
|
||||
static constexpr uint64_t MIN_DIFFICULTY = 100000;
|
||||
static constexpr size_t UNCLE_BLOCK_DEPTH = 3;
|
||||
@@ -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 {
|
||||
@@ -168,7 +168,8 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name)
|
||||
|
||||
// Hide most consensus ID bytes, we only want it on screen to show that we're on the right sidechain
|
||||
memset(buf + 8, '*', HASH_SIZE * 2 - 16);
|
||||
m_consensusIdDisplayStr.assign(buf);
|
||||
m_consensusIdDisplayStr = buf;
|
||||
|
||||
LOGINFO(1, "consensus ID = " << log::LightCyan() << m_consensusIdDisplayStr.c_str());
|
||||
|
||||
memcpy(m_consensusHash.h, m_consensusId.data(), HASH_SIZE);
|
||||
@@ -455,7 +456,7 @@ bool SideChain::get_shares(const PoolBlock* tip, std::vector<MinerShare>& shares
|
||||
hash h;
|
||||
keccak(tip->m_txkeySecSeed.h, HASH_SIZE, h.h);
|
||||
|
||||
uint64_t seed = *reinterpret_cast<uint64_t*>(h.h);
|
||||
uint64_t seed = *h.u64();
|
||||
if (seed == 0) seed = 1;
|
||||
|
||||
for (uint64_t i = 0, k; i < n - 1; ++i) {
|
||||
@@ -701,9 +702,6 @@ bool SideChain::add_block(const PoolBlock& block)
|
||||
|
||||
m_blocksByHeight[new_block->m_sidechainHeight].push_back(new_block);
|
||||
|
||||
// Pre-calculate eph_public_keys during initial sync
|
||||
launch_precalc(new_block);
|
||||
|
||||
update_depths(new_block);
|
||||
|
||||
if (new_block->m_verified) {
|
||||
@@ -742,7 +740,7 @@ void SideChain::watch_mainchain_block(const ChainMain& data, const hash& possibl
|
||||
m_watchBlockSidechainId = possible_id;
|
||||
}
|
||||
|
||||
bool SideChain::get_block_blob(const hash& id, std::vector<uint8_t>& blob) const
|
||||
const PoolBlock* SideChain::get_block_blob(const hash& id, std::vector<uint8_t>& blob) const
|
||||
{
|
||||
ReadLock lock(m_sidechainLock);
|
||||
|
||||
@@ -754,7 +752,7 @@ bool SideChain::get_block_blob(const hash& id, std::vector<uint8_t>& blob) const
|
||||
|
||||
// Don't return stale chain tip
|
||||
if (block && (block->m_txinGenHeight + 2 < m_pool->miner_data().height)) {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -765,14 +763,14 @@ bool SideChain::get_block_blob(const hash& id, std::vector<uint8_t>& blob) const
|
||||
}
|
||||
|
||||
if (!block) {
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
blob = block->serialize_mainchain_data();
|
||||
const std::vector<uint8_t> sidechain_data = block->serialize_sidechain_data();
|
||||
blob.insert(blob.end(), sidechain_data.begin(), sidechain_data.end());
|
||||
|
||||
return true;
|
||||
return block;
|
||||
}
|
||||
|
||||
bool SideChain::get_outputs_blob(PoolBlock* block, uint64_t total_reward, std::vector<uint8_t>& blob, uv_loop_t* loop) const
|
||||
@@ -781,11 +779,12 @@ bool SideChain::get_outputs_blob(PoolBlock* block, uint64_t total_reward, std::v
|
||||
|
||||
struct Data
|
||||
{
|
||||
FORCEINLINE Data() : counter(0) {}
|
||||
FORCEINLINE Data() : blockMinerWallet(nullptr), counter(0) {}
|
||||
Data(Data&&) = delete;
|
||||
Data& operator=(Data&&) = delete;
|
||||
|
||||
std::vector<MinerShare> tmpShares;
|
||||
Wallet blockMinerWallet;
|
||||
hash txkeySec;
|
||||
std::atomic<int> counter;
|
||||
};
|
||||
@@ -820,6 +819,7 @@ bool SideChain::get_outputs_blob(PoolBlock* block, uint64_t total_reward, std::v
|
||||
}
|
||||
|
||||
data = std::make_shared<Data>();
|
||||
data->blockMinerWallet = block->m_minerWallet;
|
||||
data->txkeySec = block->m_txkeySec;
|
||||
|
||||
if (!get_shares(block, data->tmpShares) || !split_reward(total_reward, data->tmpShares, tmpRewards) || (tmpRewards.size() != data->tmpShares.size())) {
|
||||
@@ -833,6 +833,14 @@ bool SideChain::get_outputs_blob(PoolBlock* block, uint64_t total_reward, std::v
|
||||
// Helper jobs call get_eph_public_key with indices in descending order
|
||||
// Current thread will process indices in ascending order so when they meet, everything will be cached
|
||||
if (loop) {
|
||||
// Avoid accessing block->m_minerWallet from other threads in "parallel_run" below
|
||||
for (MinerShare& share : data->tmpShares) {
|
||||
if (share.m_wallet == &block->m_minerWallet) {
|
||||
share.m_wallet = &data->blockMinerWallet;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
parallel_run(loop, [data]() {
|
||||
Data* d = data.get();
|
||||
hash eph_public_key;
|
||||
@@ -1296,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
|
||||
@@ -1536,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) {
|
||||
@@ -1559,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;
|
||||
@@ -1765,7 +1797,7 @@ void SideChain::update_chain_tip(const PoolBlock* block)
|
||||
" is not a longer chain than " << tip->m_sidechainId <<
|
||||
", height " << tip->m_sidechainHeight);
|
||||
}
|
||||
else if (block->m_sidechainHeight + UNCLE_BLOCK_DEPTH > tip->m_sidechainHeight) {
|
||||
else if (m_pool && (block->m_sidechainHeight + UNCLE_BLOCK_DEPTH > tip->m_sidechainHeight)) {
|
||||
LOGINFO(4, "possible uncle block: id = " << log::Gray() << block->m_sidechainId << log::NoColor() <<
|
||||
", height = " << log::Gray() << block->m_sidechainHeight);
|
||||
m_pool->update_block_template_async();
|
||||
@@ -1779,13 +1811,8 @@ void SideChain::update_chain_tip(const PoolBlock* block)
|
||||
|
||||
PoolBlock* SideChain::get_parent(const PoolBlock* block) const
|
||||
{
|
||||
if (block) {
|
||||
auto it = m_blocksById.find(block->m_parent);
|
||||
if (it != m_blocksById.end()) {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
auto it = m_blocksById.find(block->m_parent);
|
||||
return (it != m_blocksById.end()) ? it->second : nullptr;
|
||||
}
|
||||
|
||||
bool SideChain::is_longer_chain(const PoolBlock* block, const PoolBlock* candidate, bool& is_alternative) const
|
||||
@@ -1933,6 +1960,18 @@ bool SideChain::is_longer_chain(const PoolBlock* block, const PoolBlock* candida
|
||||
|
||||
void SideChain::update_depths(PoolBlock* block)
|
||||
{
|
||||
const uint64_t precalc_depth = m_chainWindowSize + UNCLE_BLOCK_DEPTH - 1;
|
||||
|
||||
auto update_depth = [this, precalc_depth](PoolBlock* b, const uint64_t new_depth) {
|
||||
const uint64_t old_depth = b->m_depth;
|
||||
if (old_depth < new_depth) {
|
||||
b->m_depth = new_depth;
|
||||
if ((old_depth < precalc_depth) && (new_depth >= precalc_depth)) {
|
||||
launch_precalc(b);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (size_t i = 1; i <= UNCLE_BLOCK_DEPTH; ++i) {
|
||||
auto it = m_blocksByHeight.find(block->m_sidechainHeight + i);
|
||||
if (it == m_blocksByHeight.end()) {
|
||||
@@ -1945,12 +1984,12 @@ void SideChain::update_depths(PoolBlock* block)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
block->m_depth = std::max(block->m_depth, child->m_depth + 1);
|
||||
update_depth(block, child->m_depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (std::find(child->m_uncles.begin(), child->m_uncles.end(), block->m_sidechainId) != child->m_uncles.end()) {
|
||||
block->m_depth = std::max(block->m_depth, child->m_depth + i);
|
||||
update_depth(block, child->m_depth + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1966,6 +2005,36 @@ void SideChain::update_depths(PoolBlock* block)
|
||||
verify_loop(block);
|
||||
}
|
||||
|
||||
for (size_t i = 1; i <= UNCLE_BLOCK_DEPTH; ++i) {
|
||||
auto it = m_blocksByHeight.find(block->m_sidechainHeight + i);
|
||||
if (it == m_blocksByHeight.end()) {
|
||||
continue;
|
||||
}
|
||||
for (PoolBlock* child : it->second) {
|
||||
const uint64_t old_depth = child->m_depth;
|
||||
|
||||
if (child->m_parent == block->m_sidechainId) {
|
||||
if (i != 1) {
|
||||
LOGWARN(3, "Block " << block->m_sidechainId << ": m_sidechainHeight is inconsistent with child's m_sidechainHeight.");
|
||||
return;
|
||||
}
|
||||
else if (block->m_depth > 0) {
|
||||
update_depth(child, block->m_depth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (std::find(child->m_uncles.begin(), child->m_uncles.end(), block->m_sidechainId) != child->m_uncles.end()) {
|
||||
if (block->m_depth > i) {
|
||||
update_depth(child, block->m_depth - i);
|
||||
}
|
||||
}
|
||||
|
||||
if (child->m_depth > old_depth) {
|
||||
blocks_to_update.push_back(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto it = m_blocksById.find(block->m_parent);
|
||||
if (it != m_blocksById.end()) {
|
||||
if (it->second->m_sidechainHeight + 1 != block->m_sidechainHeight) {
|
||||
@@ -1974,7 +2043,7 @@ void SideChain::update_depths(PoolBlock* block)
|
||||
}
|
||||
|
||||
if (it->second->m_depth < block->m_depth + 1) {
|
||||
it->second->m_depth = block->m_depth + 1;
|
||||
update_depth(it->second, block->m_depth + 1);
|
||||
blocks_to_update.push_back(it->second);
|
||||
}
|
||||
}
|
||||
@@ -1992,7 +2061,7 @@ void SideChain::update_depths(PoolBlock* block)
|
||||
|
||||
const uint64_t d = block->m_sidechainHeight - it->second->m_sidechainHeight;
|
||||
if (it->second->m_depth < block->m_depth + d) {
|
||||
it->second->m_depth = block->m_depth + d;
|
||||
update_depth(it->second, block->m_depth + d);
|
||||
blocks_to_update.push_back(it->second);
|
||||
}
|
||||
}
|
||||
@@ -2016,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!");
|
||||
@@ -2048,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
|
||||
@@ -2060,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();
|
||||
@@ -2068,23 +2141,36 @@ void SideChain::prune_old_blocks()
|
||||
m_pool->reconnect_to_host();
|
||||
}
|
||||
|
||||
if (cur_time >= m_firstPruneTime + 120) {
|
||||
if ((cur_time >= m_firstPruneTime + 120) && !m_pool->stopped()) {
|
||||
LOGINFO(0, log::LightGreen() << "[DEV] Synchronization finished successfully, stopping P2Pool now");
|
||||
#ifdef DEV_TRACK_MEMORY
|
||||
show_top_10_allocations();
|
||||
#endif
|
||||
print_status(false);
|
||||
P2PServer* server = m_pool->p2p_server();
|
||||
if (server) {
|
||||
server->print_status();
|
||||
server->print_bans();
|
||||
server->show_peers_async();
|
||||
|
||||
StratumServer* server1 = m_pool->stratum_server();
|
||||
P2PServer* server2 = m_pool->p2p_server();
|
||||
|
||||
if (server1 && server2) {
|
||||
server1->print_status();
|
||||
server2->print_status();
|
||||
|
||||
server1->print_bans();
|
||||
server2->print_bans();
|
||||
|
||||
server1->show_workers_async();
|
||||
server2->show_peers_async();
|
||||
}
|
||||
|
||||
m_pool->print_hosts();
|
||||
bkg_jobs_tracker.print_status();
|
||||
m_pool->stop();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void SideChain::get_missing_blocks(std::vector<hash>& missing_blocks) const
|
||||
void SideChain::get_missing_blocks(unordered_set<hash>& missing_blocks) const
|
||||
{
|
||||
missing_blocks.clear();
|
||||
|
||||
@@ -2096,14 +2182,14 @@ void SideChain::get_missing_blocks(std::vector<hash>& missing_blocks) const
|
||||
}
|
||||
|
||||
if (!b.second->m_parent.empty() && (m_blocksById.find(b.second->m_parent) == m_blocksById.end())) {
|
||||
missing_blocks.push_back(b.second->m_parent);
|
||||
missing_blocks.insert(b.second->m_parent);
|
||||
}
|
||||
|
||||
int num_missing_uncles = 0;
|
||||
|
||||
for (const hash& h : b.second->m_uncles) {
|
||||
if (!h.empty() && (m_blocksById.find(h) == m_blocksById.end())) {
|
||||
missing_blocks.push_back(h);
|
||||
missing_blocks.insert(h);
|
||||
|
||||
// Get no more than 2 first missing uncles at a time from each block
|
||||
// Blocks with more than 2 uncles are very rare and they will be processed in several steps
|
||||
|
||||
+5
-2
@@ -52,12 +52,12 @@ public:
|
||||
|
||||
bool add_external_block(PoolBlock& block, std::vector<hash>& missing_blocks);
|
||||
bool add_block(const PoolBlock& block);
|
||||
void get_missing_blocks(std::vector<hash>& missing_blocks) const;
|
||||
void get_missing_blocks(unordered_set<hash>& missing_blocks) const;
|
||||
|
||||
PoolBlock* find_block(const hash& id) const;
|
||||
void watch_mainchain_block(const ChainMain& data, const hash& possible_id);
|
||||
|
||||
bool get_block_blob(const hash& id, std::vector<uint8_t>& blob) const;
|
||||
const PoolBlock* get_block_blob(const hash& id, std::vector<uint8_t>& blob) const;
|
||||
bool get_outputs_blob(PoolBlock* block, uint64_t total_reward, std::vector<uint8_t>& blob, uv_loop_t* loop) const;
|
||||
|
||||
void print_status(bool obtain_sidechain_lock = true) const;
|
||||
@@ -82,8 +82,11 @@ 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; }
|
||||
#endif
|
||||
|
||||
static bool split_reward(uint64_t reward, const std::vector<MinerShare>& shares, std::vector<uint64_t>& rewards);
|
||||
|
||||
+100
-50
@@ -23,7 +23,7 @@
|
||||
#include "params.h"
|
||||
#include "p2pool_api.h"
|
||||
|
||||
static constexpr char log_category_prefix[] = "StratumServer ";
|
||||
LOG_CATEGORY(StratumServer)
|
||||
|
||||
static constexpr int DEFAULT_BACKLOG = 128;
|
||||
static constexpr uint64_t DEFAULT_BAN_TIME = 600;
|
||||
@@ -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];
|
||||
@@ -293,7 +298,7 @@ bool StratumServer::on_login(StratumClient* client, uint32_t id, const char* log
|
||||
client->m_rpcId = static_cast<StratumServer*>(client->m_owner)->get_random32();
|
||||
} while (!client->m_rpcId);
|
||||
|
||||
log::hex_buf target_hex(reinterpret_cast<const uint8_t*>(&target), sizeof(uint64_t));
|
||||
log::hex_buf target_hex(&target);
|
||||
|
||||
if (target >= TARGET_4_BYTES_LIMIT) {
|
||||
target_hex.m_data += sizeof(uint32_t);
|
||||
@@ -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);
|
||||
}
|
||||
@@ -544,6 +553,11 @@ void StratumServer::reset_share_counters()
|
||||
m_totalFailedShares = 0;
|
||||
}
|
||||
|
||||
const char* StratumServer::get_log_category() const
|
||||
{
|
||||
return log_category_prefix;
|
||||
}
|
||||
|
||||
void StratumServer::print_stratum_status() const
|
||||
{
|
||||
uint64_t hashes_15m, hashes_1h, hashes_24h, total_hashes;
|
||||
@@ -589,8 +603,8 @@ void StratumServer::print_stratum_status() const
|
||||
const uint64_t hashrate_24h = (dt_24h > 0) ? (hashes_24h / dt_24h) : 0;
|
||||
|
||||
char shares_failed_buf[64] = {};
|
||||
log::Stream s(shares_failed_buf);
|
||||
if (shares_failed) {
|
||||
log::Stream s(shares_failed_buf);
|
||||
s << log::Yellow() << "\nShares failed = " << shares_failed << log::NoColor();
|
||||
}
|
||||
|
||||
@@ -775,7 +789,7 @@ void StratumServer::on_blobs_ready()
|
||||
const bool result = send(client,
|
||||
[data, target, hashing_blob, job_id](uint8_t* buf, size_t buf_size)
|
||||
{
|
||||
log::hex_buf target_hex(reinterpret_cast<const uint8_t*>(&target), sizeof(uint64_t));
|
||||
log::hex_buf target_hex(&target);
|
||||
|
||||
if (target >= TARGET_4_BYTES_LIMIT) {
|
||||
target_hex.m_data += sizeof(uint32_t);
|
||||
@@ -854,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;
|
||||
@@ -874,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;
|
||||
}
|
||||
@@ -886,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;
|
||||
|
||||
@@ -930,7 +943,7 @@ void StratumServer::on_share_found(uv_work_t* req)
|
||||
}
|
||||
|
||||
// Send the response to miner
|
||||
const uint64_t value = *reinterpret_cast<uint64_t*>(share->m_resultHash.h + HASH_SIZE - sizeof(uint64_t));
|
||||
const uint64_t value = share->m_resultHash.u64()[HASH_SIZE / sizeof(uint64_t) - 1];
|
||||
|
||||
if (LIKELY(value < target)) {
|
||||
const uint64_t timestamp = share->m_timestamp;
|
||||
@@ -939,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;
|
||||
}
|
||||
@@ -948,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[] = {
|
||||
@@ -968,22 +979,24 @@ void StratumServer::on_after_share_found(uv_work_t* req, int /*status*/)
|
||||
|
||||
const size_t k = static_cast<size_t>(share->m_result);
|
||||
const char* reason = (k < array_size(reason_list)) ? reason_list[k] : "unknown";
|
||||
LOGWARN(0, log::Green() << "INVALID SHARE: mainchain height " << share->m_mainchainHeight << ", sidechain height " << share->m_sidechainHeight << ", diff " << share->m_sidechainDifficulty << ", client " << static_cast<char*>(client->m_addrString) << (*s ? ", user " : "") << s << ", reason: " << reason);
|
||||
LOGWARN(0, "INVALID SHARE: mainchain height " << share->m_mainchainHeight << ", sidechain height " << share->m_sidechainHeight << ", diff " << share->m_sidechainDifficulty << ", client " << static_cast<char*>(share->m_clientAddrString) << (*s ? ", user " : "") << s << ", reason: " << reason);
|
||||
}
|
||||
BACKGROUND_JOB_STOP(StratumServer::on_share_found);
|
||||
}
|
||||
|
||||
ON_SCOPE_LEAVE([share]()
|
||||
StratumServer* server = share->m_server;
|
||||
|
||||
ON_SCOPE_LEAVE([share, server]()
|
||||
{
|
||||
ASAN_POISON_MEMORY_REGION(share, sizeof(SubmittedShare));
|
||||
share->m_server->m_submittedSharesPool.push_back(share);
|
||||
server->m_submittedSharesPool.push_back(share);
|
||||
});
|
||||
|
||||
StratumServer* server = share->m_server;
|
||||
|
||||
const bool bad_share = (share->m_result == SubmittedShare::Result::LOW_DIFF) || (share->m_result == SubmittedShare::Result::INVALID_POW);
|
||||
|
||||
if ((client->m_resetCounter.load() == share->m_clientResetCounter) && (client->m_rpcId == share->m_rpcId)) {
|
||||
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)
|
||||
{
|
||||
@@ -1011,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();
|
||||
@@ -1026,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()
|
||||
@@ -1261,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;
|
||||
}
|
||||
|
||||
@@ -1324,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
|
||||
@@ -1338,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;
|
||||
|
||||
@@ -97,7 +98,7 @@ public:
|
||||
void reset_share_counters();
|
||||
|
||||
private:
|
||||
const char* get_category() const override { return "StratumServer "; }
|
||||
const char* get_log_category() const override;
|
||||
|
||||
void print_stratum_status() const;
|
||||
void update_auto_diff(StratumClient* client, const uint64_t timestamp, const uint64_t hashes);
|
||||
@@ -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;
|
||||
|
||||
+39
-16
@@ -27,7 +27,7 @@ TCPServer::TCPServer(int default_backlog, allocate_client_callback allocate_new_
|
||||
: m_allocateNewClient(allocate_new_client)
|
||||
, m_defaultBacklog(default_backlog)
|
||||
, m_loopThread{}
|
||||
, m_loopThreadRunning(false)
|
||||
, m_loopThreadCreated(false)
|
||||
#ifdef WITH_UPNP
|
||||
, m_portMapping(0)
|
||||
#endif
|
||||
@@ -251,6 +251,8 @@ void TCPServer::start_listening(const std::string& listen_addresses, bool upnp)
|
||||
LOGERR(1, "failed to start event loop thread, error " << uv_err_name(err));
|
||||
PANIC_STOP();
|
||||
}
|
||||
|
||||
m_loopThreadCreated = true;
|
||||
}
|
||||
|
||||
bool TCPServer::connect_to_peer(bool is_v6, const char* ip, int port)
|
||||
@@ -379,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));
|
||||
}
|
||||
}
|
||||
@@ -393,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));
|
||||
}
|
||||
}
|
||||
@@ -417,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
|
||||
@@ -474,7 +477,7 @@ void TCPServer::shutdown_tcp()
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_loopThreadRunning.load()) {
|
||||
if (m_loopThreadCreated) {
|
||||
uv_thread_join(&m_loopThread);
|
||||
}
|
||||
|
||||
@@ -573,13 +576,16 @@ bool TCPServer::send_internal(Client* client, Callback<size_t, uint8_t*, size_t>
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* TCPServer::get_log_category() const
|
||||
{
|
||||
return log_category_prefix;
|
||||
}
|
||||
|
||||
void TCPServer::loop(void* data)
|
||||
{
|
||||
TCPServer* server = static_cast<TCPServer*>(data);
|
||||
server->m_loopThreadRunning.exchange(true);
|
||||
ON_SCOPE_LEAVE([server]() { server->m_loopThreadRunning.exchange(false); });
|
||||
|
||||
log_category_prefix = server->get_category();
|
||||
log_category_prefix = server->get_log_category();
|
||||
|
||||
LOGINFO(1, "event loop started");
|
||||
server_event_loop_thread = data;
|
||||
@@ -592,7 +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());
|
||||
c->asan_poison_this();
|
||||
|
||||
server->m_writeBuffers.emplace(capacity, wb);
|
||||
server->m_preallocatedClients.emplace_back(c);
|
||||
@@ -776,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);
|
||||
}
|
||||
|
||||
@@ -856,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)
|
||||
@@ -956,7 +965,7 @@ TCPServer::Client* TCPServer::get_client()
|
||||
|
||||
void TCPServer::return_client(Client* c)
|
||||
{
|
||||
ASAN_POISON_MEMORY_REGION(c, c->size());
|
||||
c->asan_poison_this();
|
||||
m_preallocatedClients.push_back(c);
|
||||
}
|
||||
|
||||
@@ -1098,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);
|
||||
}
|
||||
@@ -1203,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;
|
||||
@@ -1236,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) {
|
||||
@@ -1255,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
|
||||
|
||||
+9
-3
@@ -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,
|
||||
@@ -143,13 +149,13 @@ private:
|
||||
std::vector<uv_tcp_t*> m_listenSockets;
|
||||
|
||||
protected:
|
||||
virtual const char* get_category() const { return "TCPServer "; }
|
||||
virtual const char* get_log_category() const;
|
||||
|
||||
std::vector<uint8_t> m_callbackBuf;
|
||||
int m_defaultBacklog;
|
||||
|
||||
uv_thread_t m_loopThread;
|
||||
std::atomic<bool> m_loopThreadRunning;
|
||||
std::atomic<bool> m_loopThreadCreated;
|
||||
|
||||
static void loop(void* data);
|
||||
|
||||
|
||||
+33
-11
@@ -40,11 +40,17 @@
|
||||
#include <resolv.h>
|
||||
#endif
|
||||
|
||||
static constexpr char log_category_prefix[] = "Util ";
|
||||
LOG_CATEGORY(Util)
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
const char* VERSION = "v" STR2(P2POOL_VERSION_MAJOR) "." STR2(P2POOL_VERSION_MINOR) " (built"
|
||||
#if defined(P2POOL_VERSION_PATCH) && (P2POOL_VERSION_PATCH > 0)
|
||||
#define P2POOL_VERSION_PATCH_STR "." STR2(P2POOL_VERSION_PATCH)
|
||||
#else
|
||||
#define P2POOL_VERSION_PATCH_STR ""
|
||||
#endif
|
||||
|
||||
const char* VERSION = "v" STR2(P2POOL_VERSION_MAJOR) "." STR2(P2POOL_VERSION_MINOR) P2POOL_VERSION_PATCH_STR " (built"
|
||||
#if defined(__clang__)
|
||||
" with clang/" __clang_version__
|
||||
#elif defined(__GNUC__)
|
||||
@@ -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 };
|
||||
|
||||
@@ -141,7 +161,7 @@ NOINLINE difficulty_type& difficulty_type::operator/=(difficulty_type b)
|
||||
|
||||
NOINLINE bool difficulty_type::check_pow(const hash& pow_hash) const
|
||||
{
|
||||
const uint64_t* a = reinterpret_cast<const uint64_t*>(pow_hash.h);
|
||||
const uint64_t* a = pow_hash.u64();
|
||||
|
||||
uint64_t result[6] = {};
|
||||
uint64_t product[6] = {};
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -602,10 +626,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;
|
||||
|
||||
+24
-4
@@ -35,10 +35,19 @@
|
||||
namespace p2pool {
|
||||
|
||||
#define P2POOL_VERSION_MAJOR 3
|
||||
#define P2POOL_VERSION_MINOR 5
|
||||
#define P2POOL_VERSION_MINOR 8
|
||||
#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)
|
||||
@@ -301,12 +316,17 @@ bool get_dns_txt_records_base(const std::string& host, Callback<void, const char
|
||||
template<typename T>
|
||||
FORCEINLINE bool get_dns_txt_records(const std::string& host, T&& callback) { return get_dns_txt_records_base(host, Callback<void, const char*, size_t>::Derived<T>(std::move(callback))); }
|
||||
|
||||
#ifdef DEV_TRACK_MEMORY
|
||||
void show_top_10_allocations();
|
||||
#endif
|
||||
|
||||
} // namespace p2pool
|
||||
|
||||
void memory_tracking_start();
|
||||
void memory_tracking_stop();
|
||||
bool memory_tracking_stop();
|
||||
void p2pool_usage();
|
||||
void p2pool_version();
|
||||
int p2pool_test();
|
||||
|
||||
namespace robin_hood {
|
||||
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@
|
||||
#include "json_parsers.h"
|
||||
#include <rapidjson/document.h>
|
||||
|
||||
static constexpr char log_category_prefix[] = "ZMQReader ";
|
||||
LOG_CATEGORY(ZMQReader)
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(p2pool_tests)
|
||||
|
||||
option(STATIC_LIBS "Use locally built libuv and libzmq static libs" OFF)
|
||||
@@ -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
|
||||
@@ -96,7 +97,7 @@ include_directories(googletest/googletest/include)
|
||||
|
||||
if (WIN32)
|
||||
set(LIBS ${LIBS} ws2_32 iphlpapi userenv psapi dnsapi dbghelp)
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
if ((CMAKE_CXX_COMPILER_ID MATCHES GNU) OR (CMAKE_CXX_COMPILER_ID MATCHES Clang))
|
||||
set(LIBS ${LIBS} bcrypt)
|
||||
endif()
|
||||
add_definitions(-DCURL_STATICLIB)
|
||||
|
||||
@@ -27,7 +27,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES GNU)
|
||||
endif()
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
set(GENERAL_FLAGS "")
|
||||
set(WARNING_FLAGS "/Wall /sdl")
|
||||
set(WARNING_FLAGS "/W4 /sdl")
|
||||
set(SECURITY_FLAGS "/GS /guard:cf")
|
||||
set(OPTIMIZATION_FLAGS "/O2 /Oi /Ob2 /Ot /DNDEBUG /GL")
|
||||
|
||||
@@ -41,7 +41,12 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${GENERAL_FLAGS} ${WARNING_FLAGS} ${SECURITY_FLAGS} /Ob1 /Ot /Zi /MT")
|
||||
|
||||
elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
set(GENERAL_FLAGS "-pthread")
|
||||
if (WIN32)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
||||
else()
|
||||
set(GENERAL_FLAGS "-pthread")
|
||||
endif()
|
||||
|
||||
set(WARNING_FLAGS "-Wall -Wextra -Wno-undefined-internal")
|
||||
set(OPTIMIZATION_FLAGS "-Ofast -funroll-loops -fmerge-all-constants -flto")
|
||||
|
||||
|
||||
+1
-1
Submodule tests/googletest updated: 58d77fa807...f8d7d77c06
@@ -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
|
||||
@@ -74,8 +74,8 @@ TEST(block_template, update)
|
||||
ASSERT_EQ(diff, 300346053753ULL);
|
||||
ASSERT_EQ(sidechain_diff, sidechain.difficulty());
|
||||
ASSERT_EQ(seed_hash, data.seed_hash);
|
||||
ASSERT_EQ(nonce_offset, 39);
|
||||
ASSERT_EQ(template_id, 1);
|
||||
ASSERT_EQ(nonce_offset, 39U);
|
||||
ASSERT_EQ(template_id, 1U);
|
||||
|
||||
hash blobs_hash;
|
||||
keccak(blobs.data(), static_cast<int>(blobs.size()), blobs_hash.h);
|
||||
@@ -105,8 +105,8 @@ TEST(block_template, update)
|
||||
ASSERT_EQ(diff, 300346053753ULL);
|
||||
ASSERT_EQ(sidechain_diff, sidechain.difficulty());
|
||||
ASSERT_EQ(seed_hash, data.seed_hash);
|
||||
ASSERT_EQ(nonce_offset, 39);
|
||||
ASSERT_EQ(template_id, 2);
|
||||
ASSERT_EQ(nonce_offset, 39U);
|
||||
ASSERT_EQ(template_id, 2U);
|
||||
|
||||
keccak(blobs.data(), static_cast<int>(blobs.size()), blobs_hash.h);
|
||||
ASSERT_EQ(blobs_hash, H("c74d295a9cb7e808030284e2169a6f05b685a11c6c577a774d5eb8fad175d5cd"));
|
||||
|
||||
@@ -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
|
||||
@@ -567,8 +567,8 @@ TEST(difficulty_type, check_pow)
|
||||
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
// Random difficulty between 300G and 400G
|
||||
difficulty_type diff{ 300000000000ull + (r() % 100000000000ull), 0 };
|
||||
hash h;
|
||||
diff.lo = 300000000000ull + (r() % 100000000000ull);
|
||||
diff.hi = 0;
|
||||
|
||||
// All zeros
|
||||
memset(h.h, 0, HASH_SIZE);
|
||||
|
||||
@@ -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
|
||||
|
||||
Binary file not shown.
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
+3
-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
|
||||
@@ -18,9 +18,11 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
void p2pool_usage() {}
|
||||
namespace p2pool { void set_main_thread(); }
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
p2pool::set_main_thread();
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -57,33 +57,41 @@ TEST(pool_block, deserialize)
|
||||
int outputs_offset, outputs_blob_size;
|
||||
const std::vector<uint8_t> mainchain_data = b.serialize_mainchain_data(&header_size, &miner_tx_size, &outputs_offset, &outputs_blob_size);
|
||||
|
||||
ASSERT_EQ(mainchain_data.size(), 1757);
|
||||
ASSERT_EQ(header_size, 43);
|
||||
ASSERT_EQ(miner_tx_size, 1457);
|
||||
ASSERT_EQ(mainchain_data.size(), 1757U);
|
||||
ASSERT_EQ(header_size, 43U);
|
||||
ASSERT_EQ(miner_tx_size, 1457U);
|
||||
ASSERT_EQ(outputs_offset, 54);
|
||||
ASSERT_EQ(outputs_blob_size, 1371);
|
||||
|
||||
ASSERT_EQ(b.m_majorVersion, 16);
|
||||
ASSERT_EQ(b.m_minorVersion, 16);
|
||||
ASSERT_EQ(b.m_timestamp, 1679221824);
|
||||
ASSERT_EQ(b.m_nonce, 1247);
|
||||
ASSERT_EQ(b.m_txinGenHeight, 2845298);
|
||||
ASSERT_EQ(b.m_outputs.size(), 35);
|
||||
ASSERT_EQ(b.m_extraNonceSize, 4);
|
||||
ASSERT_EQ(b.m_extraNonce, 1482827308);
|
||||
ASSERT_EQ(b.m_transactions.size(), 9);
|
||||
ASSERT_EQ(b.m_uncles.size(), 0);
|
||||
ASSERT_EQ(b.m_sidechainHeight, 4674483);
|
||||
ASSERT_EQ(b.m_difficulty.lo, 1854596983);
|
||||
ASSERT_EQ(b.m_difficulty.hi, 0);
|
||||
ASSERT_EQ(b.m_majorVersion, 16U);
|
||||
ASSERT_EQ(b.m_minorVersion, 16U);
|
||||
ASSERT_EQ(b.m_timestamp, 1679221824U);
|
||||
ASSERT_EQ(b.m_nonce, 1247U);
|
||||
ASSERT_EQ(b.m_txinGenHeight, 2845298U);
|
||||
ASSERT_EQ(b.m_outputs.size(), 35U);
|
||||
ASSERT_EQ(b.m_extraNonceSize, 4U);
|
||||
ASSERT_EQ(b.m_extraNonce, 1482827308U);
|
||||
ASSERT_EQ(b.m_transactions.size(), 9U);
|
||||
ASSERT_EQ(b.m_uncles.size(), 0U);
|
||||
ASSERT_EQ(b.m_sidechainHeight, 4674483U);
|
||||
ASSERT_EQ(b.m_difficulty.lo, 1854596983U);
|
||||
ASSERT_EQ(b.m_difficulty.hi, 0U);
|
||||
ASSERT_EQ(b.m_cumulativeDifficulty.lo, 7172845253120126ull);
|
||||
ASSERT_EQ(b.m_cumulativeDifficulty.hi, 0);
|
||||
ASSERT_EQ(b.m_depth, 0);
|
||||
ASSERT_EQ(b.m_cumulativeDifficulty.hi, 0U);
|
||||
ASSERT_EQ(b.m_depth, 0U);
|
||||
ASSERT_EQ(b.m_verified, false);
|
||||
ASSERT_EQ(b.m_invalid, false);
|
||||
ASSERT_EQ(b.m_broadcasted, false);
|
||||
ASSERT_EQ(b.m_wantBroadcast, false);
|
||||
|
||||
hash seed;
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "6fc9c4a55eb513eb31955c084d9342e0082987f9e42da042449b7c9001176d3a";
|
||||
s >> seed;
|
||||
}
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
class RandomX_Hasher_Test : public RandomX_Hasher_Base
|
||||
{
|
||||
public:
|
||||
@@ -107,8 +115,12 @@ TEST(pool_block, deserialize)
|
||||
return false;
|
||||
}
|
||||
} hasher;
|
||||
#else
|
||||
RandomX_Hasher hasher(nullptr);
|
||||
hasher.set_seed(seed);
|
||||
#endif
|
||||
|
||||
hash seed, pow_hash;
|
||||
hash pow_hash;
|
||||
ASSERT_EQ(b.get_pow_hash(&hasher, 0, seed, pow_hash), true);
|
||||
|
||||
std::stringstream s;
|
||||
@@ -130,14 +142,14 @@ TEST(pool_block, verify)
|
||||
const char* m_fileName;
|
||||
uint64_t m_txinGenHeight;
|
||||
uint64_t m_sidechainHeight;
|
||||
bool m_shuffle;
|
||||
} tests[2] = {
|
||||
{ "default", "sidechain_dump.dat", 2870010, 4957203 },
|
||||
{ "mini", "sidechain_dump_mini.dat", 2870010, 4414446 },
|
||||
{ "default", "sidechain_dump.dat", 2870010, 4957203, true },
|
||||
{ "mini", "sidechain_dump_mini.dat", 2870010, 4414446, false },
|
||||
};
|
||||
|
||||
for (const STest& t : tests)
|
||||
{
|
||||
PoolBlock b;
|
||||
SideChain sidechain(nullptr, NetworkType::Mainnet, t.m_poolName);
|
||||
|
||||
// Difficulty of block 2869248
|
||||
@@ -151,17 +163,40 @@ TEST(pool_block, verify)
|
||||
f.read(reinterpret_cast<char*>(buf.data()), buf.size());
|
||||
ASSERT_EQ(f.good(), true);
|
||||
|
||||
std::vector<PoolBlock*> blocks;
|
||||
for (const uint8_t *p = buf.data(), *e = buf.data() + buf.size(); p < e;) {
|
||||
ASSERT_TRUE(p + sizeof(uint32_t) <= e);
|
||||
const uint32_t n = *reinterpret_cast<const uint32_t*>(p);
|
||||
p += sizeof(uint32_t);
|
||||
|
||||
ASSERT_TRUE(p + n <= e);
|
||||
ASSERT_EQ(b.deserialize(p, n, sidechain, nullptr, false), 0);
|
||||
|
||||
PoolBlock* b = new PoolBlock();
|
||||
ASSERT_EQ(b->deserialize(p, n, sidechain, nullptr, false), 0);
|
||||
p += n;
|
||||
|
||||
ASSERT_TRUE(sidechain.add_block(b));
|
||||
ASSERT_TRUE(sidechain.find_block(b.m_sidechainId) != nullptr);
|
||||
blocks.push_back(b);
|
||||
}
|
||||
|
||||
if (t.m_shuffle) {
|
||||
std::mt19937_64 rng;
|
||||
|
||||
for (uint64_t i = 0, k, n = blocks.size(); i < n - 1; ++i) {
|
||||
umul128(rng(), n - i, &k);
|
||||
std::swap(blocks[i], blocks[i + k]);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint64_t i = 0, n = blocks.size(); i < n; ++i) {
|
||||
ASSERT_TRUE(sidechain.add_block(*blocks[i]));
|
||||
ASSERT_TRUE(sidechain.find_block(blocks[i]->m_sidechainId) != nullptr);
|
||||
delete blocks[i];
|
||||
}
|
||||
|
||||
for (auto it = sidechain.blocksById().begin(); it != sidechain.blocksById().end(); ++it) {
|
||||
const PoolBlock* b = it->second;
|
||||
ASSERT_TRUE(b->m_verified);
|
||||
ASSERT_FALSE(b->m_invalid);
|
||||
}
|
||||
|
||||
const PoolBlock* tip = sidechain.chainTip();
|
||||
|
||||
+91
-14
@@ -1,37 +1,114 @@
|
||||
# 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
|
||||
import json
|
||||
|
||||
f = open('stratum_dummy' + sys.argv[1] + '.log', 'wb');
|
||||
f = open('stratum_dummy' + sys.argv[1] + '.log', 'wb')
|
||||
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.settimeout(1)
|
||||
sock.setblocking(True)
|
||||
f.write(b'Connecting')
|
||||
f.flush()
|
||||
|
||||
time.sleep(5)
|
||||
while True:
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.settimeout(1)
|
||||
sock.setblocking(True)
|
||||
|
||||
while sock.connect_ex(('127.0.0.1', 3333)) != 0:
|
||||
f.write(b'.\n')
|
||||
if sock.connect_ex(('127.0.0.1', 3333)) == 0:
|
||||
break;
|
||||
|
||||
sock.close()
|
||||
|
||||
f.write(b'.')
|
||||
f.flush()
|
||||
print('.')
|
||||
time.sleep(1)
|
||||
|
||||
diff = '';
|
||||
f.write(b'\n')
|
||||
f.flush()
|
||||
|
||||
diff = ''
|
||||
|
||||
if (sys.argv[1] == '2'):
|
||||
diff = '+1000';
|
||||
diff = '+1000'
|
||||
if (sys.argv[1] == '3'):
|
||||
diff = '+10000000';
|
||||
diff = '+10000000'
|
||||
|
||||
request = '{"id":1,"method":"login","params":{"login":"x' + diff + '"}}\n'
|
||||
msg_id = 1
|
||||
|
||||
request = '{"id":' + str(msg_id) + ',"method":"login","params":{"login":"x' + diff + '"}}\n'
|
||||
msg_id += 1
|
||||
s = '-> ' + request
|
||||
print(s, end='')
|
||||
sock.sendall(request.encode('utf-8'))
|
||||
|
||||
f.write(s.encode('utf-8'))
|
||||
f.flush()
|
||||
|
||||
rpc_id = ''
|
||||
|
||||
while True:
|
||||
data = sock.recv(1024)
|
||||
if len(data) == 0:
|
||||
break;
|
||||
f.write(data)
|
||||
break
|
||||
|
||||
s = '<- ' + data.decode('utf-8')
|
||||
print(s, end='')
|
||||
|
||||
f.write(s.encode('utf-8'))
|
||||
f.flush()
|
||||
print(data.decode('utf-8'))
|
||||
|
||||
obj = json.loads(data)
|
||||
job_id = ''
|
||||
|
||||
if ('method' in obj) and ('params' in obj) and (obj['method'] == 'job'):
|
||||
job_id = obj['params']['job_id']
|
||||
target = obj['params']['target']
|
||||
elif ('result' in obj) and ('job' in obj['result']):
|
||||
if ('id' in obj['result']):
|
||||
rpc_id = obj['result']['id']
|
||||
job_id = obj['result']['job']['job_id']
|
||||
target = obj['result']['job']['target']
|
||||
|
||||
if (job_id != ''):
|
||||
if (msg_id < 4):
|
||||
result = ('f' if (msg_id == 2) else '0') * 64
|
||||
request = '{"id":' + str(msg_id) + ',"method":"submit","params":{"id":"' + rpc_id + '","job_id":"' + job_id + '","nonce":"ffffffff","result":"' + result + '"}}\n'
|
||||
elif (msg_id == 4):
|
||||
request = '{"id":' + str(msg_id) + ',"method":"keepalived"}\n'
|
||||
else:
|
||||
t = bytearray.fromhex(target)
|
||||
for i in range(len(t)):
|
||||
if (t[i] > 0):
|
||||
t[i] -= 1
|
||||
break
|
||||
else:
|
||||
t[i] = 255
|
||||
|
||||
result = ('f' * (64 - len(target))) + t.hex()
|
||||
request = '{"id":' + str(msg_id) + ',"method":"submit","params":{"id":"' + rpc_id + '","job_id":"' + job_id + '","nonce":"ffffffff","result":"' + result + '"}}\n'
|
||||
|
||||
msg_id += 1
|
||||
s = '-> ' + request
|
||||
print(s, end='')
|
||||
sock.sendall(request.encode('utf-8'))
|
||||
|
||||
f.write(s.encode('utf-8'))
|
||||
f.flush()
|
||||
|
||||
sock.close()
|
||||
f.close()
|
||||
|
||||
@@ -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