Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0d7b110f15 | |||
| 7cd21f5d0e | |||
| 886da5a73e | |||
| bfa30254df | |||
| b589d373ea | |||
| 8333f7800f | |||
| 91fb15e967 | |||
| e0c1d9377c | |||
| 3f80244d84 | |||
| 433a1991bc | |||
| 915be9e39f | |||
| b9e415c659 | |||
| 1e2e5b85aa | |||
| 40999f0056 | |||
| cf51fe5273 | |||
| 3154b61fc6 | |||
| f9831500e4 | |||
| e9d49b2a1d | |||
| 5eabfb0a1a | |||
| 3fc68e680a | |||
| 1bd9ff1379 | |||
| 9a0a96f990 | |||
| 604ef13aa6 | |||
| 293c6f3930 | |||
| 1f3872254d | |||
| 27a2461d1d | |||
| 70298cd065 | |||
| f655fd1e30 | |||
| 9abe993bb0 | |||
| 2a30901ba5 | |||
| 2c29092b7a | |||
| 7d610f61d5 | |||
| 7d632fdc85 |
@@ -2,6 +2,7 @@ name: C/C++ CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master"]
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
@@ -88,7 +89,7 @@ jobs:
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release -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)
|
||||
make -j$(nproc) p2pool_tests
|
||||
|
||||
- name: Run tests
|
||||
shell: alpine.sh {0}
|
||||
@@ -156,7 +157,7 @@ jobs:
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=${{ matrix.config.c }} -DCMAKE_CXX_COMPILER=${{ matrix.config.cpp }} -DCMAKE_C_FLAGS='${{ matrix.config.flags }}' -DCMAKE_CXX_FLAGS='${{ matrix.config.flags }}' -DCMAKE_POLICY_VERSION_MINIMUM="3.5"
|
||||
make -j$(nproc)
|
||||
make -j$(nproc) p2pool_tests
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
@@ -236,7 +237,7 @@ jobs:
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release -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 -DCMAKE_POLICY_VERSION_MINIMUM="3.5"
|
||||
make -j$(nproc)
|
||||
make -j$(nproc) p2pool_tests
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
@@ -315,7 +316,7 @@ jobs:
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release -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 -DCMAKE_POLICY_VERSION_MINIMUM="3.5"
|
||||
make -j$(nproc)
|
||||
make -j$(nproc) p2pool_tests
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
@@ -337,8 +338,8 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- {c: "gcc", cxx: "g++", flags: "-ffunction-sections -Wno-error=maybe-uninitialized -Wno-error=attributes -Wno-error=cpp"}
|
||||
- {c: "clang", cxx: "clang++", flags: "-fuse-ld=lld -Wno-unused-command-line-argument -Wno-nan-infinity-disabled -Wno-error=cpp"}
|
||||
- {c: "gcc", cxx: "g++", flags: "-ffunction-sections -Wno-error=maybe-uninitialized -Wno-error=attributes"}
|
||||
- {c: "clang", cxx: "clang++", flags: "-fuse-ld=lld -Wno-unused-command-line-argument -Wno-nan-infinity-disabled"}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
@@ -399,7 +400,7 @@ jobs:
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release -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 -DOPENSSL_NO_ASM=ON
|
||||
make -j$(nproc)
|
||||
make -j$(nproc) p2pool_tests
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
@@ -540,7 +541,7 @@ jobs:
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER="$(brew --prefix llvm@15)/bin/clang" -DCMAKE_CXX_COMPILER="$(brew --prefix llvm@15)/bin/clang++" -DCMAKE_AR="$(brew --prefix llvm@15)/bin/llvm-ar" -DCMAKE_RANLIB="$(brew --prefix llvm@15)/bin/llvm-ranlib" -DCMAKE_C_FLAGS='-flto -target x86_64-apple-macos10.13 -Wno-overriding-t-option' -DCMAKE_CXX_FLAGS='-flto -target x86_64-apple-macos10.13 -Wno-overriding-t-option' -DCMAKE_ASM_FLAGS='-target x86_64-apple-macos10.13' -DSTATIC_LIBS=ON
|
||||
make -j4
|
||||
make -j4 p2pool_tests
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
@@ -608,7 +609,7 @@ jobs:
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release -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
|
||||
make -j3 p2pool_tests
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
|
||||
@@ -2,6 +2,7 @@ name: clang-tidy
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master"]
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
|
||||
@@ -13,6 +13,7 @@ name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master"]
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
|
||||
@@ -2,6 +2,7 @@ name: cppcheck
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master"]
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
@@ -25,10 +26,10 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Checkout cppcheck
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: danmar/cppcheck
|
||||
path: cppcheck-main
|
||||
run: |
|
||||
git clone https://github.com/danmar/cppcheck cppcheck-main
|
||||
cd cppcheck-main
|
||||
git checkout 6d7dc76052ad36128fae93f994d6a2bf57e93103
|
||||
|
||||
- name: Build cppcheck
|
||||
run: |
|
||||
@@ -73,10 +74,10 @@ jobs:
|
||||
submodules: recursive
|
||||
|
||||
- name: Checkout cppcheck
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: danmar/cppcheck
|
||||
path: cppcheck-main
|
||||
run: |
|
||||
git clone https://github.com/danmar/cppcheck cppcheck-main
|
||||
cd cppcheck-main
|
||||
git checkout 6d7dc76052ad36128fae93f994d6a2bf57e93103
|
||||
|
||||
- name: Build cppcheck
|
||||
run: |
|
||||
|
||||
@@ -10,6 +10,7 @@ name: Microsoft C++ Code Analysis
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master"]
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
name: source-snapshot
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
push:
|
||||
branches: ["master"]
|
||||
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
source-snapshot:
|
||||
|
||||
@@ -2,6 +2,7 @@ name: Sync test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master"]
|
||||
paths-ignore:
|
||||
- 'docker-compose/**'
|
||||
- 'docs/**'
|
||||
@@ -68,7 +69,7 @@ jobs:
|
||||
python ../tests/src/stratum_dummy.py 2 &
|
||||
python ../tests/src/stratum_dummy.py 3 &
|
||||
sudo sysctl vm.mmap_rnd_bits=28
|
||||
TSAN_OPTIONS="suppressions=../tests/src/tsan_sup.txt halt_on_error=1 history_size=4" ./p2pool --host xmrbandwagon.hopto.org --rpc-port 18081 --zmq-port 18084 --host node.richfowler.net --rpc-port 18089 --zmq-port 18084 --rpc-ssl --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
TSAN_OPTIONS="suppressions=../tests/src/tsan_sup.txt halt_on_error=1 history_size=4" ./p2pool --host node.monerodevs.org --rpc-port 18089 --zmq-port 18084 --host node.richfowler.net --rpc-port 18089 --zmq-port 18084 --rpc-ssl --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
@@ -154,7 +155,7 @@ jobs:
|
||||
python ../tests/src/stratum_dummy.py 2 &
|
||||
python ../tests/src/stratum_dummy.py 3 &
|
||||
sudo sysctl vm.mmap_rnd_bits=28
|
||||
MSAN_OPTIONS="halt_on_error=1" ./p2pool --host xmrbandwagon.hopto.org --rpc-port 18081 --zmq-port 18084 --host node.richfowler.net --rpc-port 18089 --zmq-port 18084 --rpc-ssl --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
MSAN_OPTIONS="halt_on_error=1" ./p2pool --host node.monerodevs.org --rpc-port 18089 --zmq-port 18084 --host node.richfowler.net --rpc-port 18089 --zmq-port 18084 --rpc-ssl --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
@@ -201,7 +202,7 @@ jobs:
|
||||
python ../tests/src/stratum_dummy.py 2 &
|
||||
python ../tests/src/stratum_dummy.py 3 &
|
||||
sudo sysctl vm.mmap_rnd_bits=28
|
||||
UBSAN_OPTIONS="suppressions=../tests/src/ubsan_sup.txt halt_on_error=1" ./p2pool --host xmrbandwagon.hopto.org --rpc-port 18081 --zmq-port 18084 --host node.richfowler.net --rpc-port 18089 --zmq-port 18084 --rpc-ssl --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
UBSAN_OPTIONS="suppressions=../tests/src/ubsan_sup.txt halt_on_error=1" ./p2pool --host node.monerodevs.org --rpc-port 18089 --zmq-port 18084 --host node.richfowler.net --rpc-port 18089 --zmq-port 18084 --rpc-ssl --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
@@ -248,7 +249,7 @@ jobs:
|
||||
python ../tests/src/stratum_dummy.py 2 &
|
||||
python ../tests/src/stratum_dummy.py 3 &
|
||||
sudo sysctl vm.mmap_rnd_bits=28
|
||||
ASAN_OPTIONS="detect_stack_use_after_return=1 atexit=1" ./p2pool --host xmrbandwagon.hopto.org --rpc-port 18081 --zmq-port 18084 --host node.richfowler.net --rpc-port 18089 --zmq-port 18084 --rpc-ssl --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
ASAN_OPTIONS="detect_stack_use_after_return=1 atexit=1" ./p2pool --host node.monerodevs.org --rpc-port 18089 --zmq-port 18084 --host node.richfowler.net --rpc-port 18089 --zmq-port 18084 --rpc-ssl --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
@@ -317,7 +318,7 @@ jobs:
|
||||
python3 ../tests/src/stratum_dummy.py 1 &
|
||||
python3 ../tests/src/stratum_dummy.py 2 &
|
||||
python3 ../tests/src/stratum_dummy.py 3 &
|
||||
./p2pool --host xmrbandwagon.hopto.org --rpc-port 18081 --zmq-port 18084 --host node.richfowler.net --rpc-port 18089 --zmq-port 18084 --rpc-ssl --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
./p2pool --host node.monerodevs.org --rpc-port 18089 --zmq-port 18084 --host node.richfowler.net --rpc-port 18089 --zmq-port 18084 --rpc-ssl --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
@@ -362,7 +363,7 @@ jobs:
|
||||
start python ../../tests/src/stratum_dummy.py 1
|
||||
start python ../../tests/src/stratum_dummy.py 2
|
||||
start python ../../tests/src/stratum_dummy.py 3
|
||||
p2pool.exe --host xmrbandwagon.hopto.org --rpc-port 18081 --zmq-port 18084 --host node.richfowler.net --rpc-port 18089 --zmq-port 18084 --rpc-ssl --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
p2pool.exe --host node.monerodevs.org --rpc-port 18089 --zmq-port 18084 --host node.richfowler.net --rpc-port 18089 --zmq-port 18084 --rpc-ssl --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
@@ -405,7 +406,7 @@ jobs:
|
||||
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 1"
|
||||
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 2"
|
||||
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 3"
|
||||
./p2pool.exe --host xmrbandwagon.hopto.org --rpc-port 18081 --zmq-port 18084 --host node.richfowler.net --rpc-port 18089 --zmq-port 18084 --rpc-ssl --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
./p2pool.exe --host node.monerodevs.org --rpc-port 18089 --zmq-port 18084 --host node.richfowler.net --rpc-port 18089 --zmq-port 18084 --rpc-ssl --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6
|
||||
|
||||
- name: Check p2pool.log
|
||||
run: |
|
||||
|
||||
+7
-1
@@ -17,7 +17,9 @@ option(WITH_RANDOMX "Include the RandomX library in the build. If this is turned
|
||||
option(WITH_LTO "Use link-time compiler optimization (if linking fails for you, run cmake with -DWITH_LTO=OFF)" ON)
|
||||
option(WITH_UPNP "Include UPnP support. If this is turned off, p2pool will not be able to configure port forwarding on UPnP-enabled routers." ON)
|
||||
option(WITH_GRPC "Include gRPC support. If this is turned off, p2pool will not be able to merge mine with Tari." ON)
|
||||
option(WITH_TLS "Include TLS support. If this is turned off, p2pool will not support Stratum TLS connections." ON)
|
||||
option(WITH_TLS "Include TLS support. If this is turned off, p2pool will not support Stratum TLS connections, and lack many other security features. It's recommended to keep it ON!" ON)
|
||||
|
||||
option(WITH_MERGE_MINING_DONATION "Merge mine donations to the author. This doesn't affect your hashrate or payouts in any way - only unused merge mining capacity will be utilised. If you merge mine yourself, your settings will take priority." ON)
|
||||
|
||||
option(DEV_TEST_SYNC "[Developer only] Sync test, stop p2pool after sync is complete" OFF)
|
||||
option(DEV_WITH_TSAN "[Developer only] Compile with thread sanitizer" OFF)
|
||||
@@ -56,6 +58,10 @@ if (WITH_UPNP)
|
||||
set(LIBS ${LIBS} libminiupnpc-static)
|
||||
endif()
|
||||
|
||||
if (WITH_MERGE_MINING_DONATION)
|
||||
add_definitions(-DWITH_MERGE_MINING_DONATION)
|
||||
endif()
|
||||
|
||||
if (DEV_TEST_SYNC)
|
||||
add_definitions(-DDEV_TEST_SYNC)
|
||||
endif()
|
||||
|
||||
@@ -111,7 +111,7 @@ In order to continue mining on P2Pool, you must update both Monero and P2Pool so
|
||||
|
||||
### Merge mining
|
||||
|
||||
Merge mining will be available in P2Pool after the fork on October 12th, 2024. Version 4.0 or newer is required to use it.
|
||||
Merge mining is available in P2Pool since the fork that happened on October 12th, 2024. Version 4.0 or newer is required to use it.
|
||||
|
||||
- Blockchains that will support [Merge mining RPC API](https://github.com/SChernykh/p2pool/blob/master/docs/MERGE_MINING.MD#proposed-rpc-api)
|
||||
- [Townforge](https://townforge.net/) supports it in their [tmp-mm branch](https://git.townforge.net/townforge/townforge/src/branch/tmp-mm) (not released yet)
|
||||
@@ -120,11 +120,27 @@ Merge mining will be available in P2Pool after the fork on October 12th, 2024. V
|
||||
p2pool.exe --wallet YOUR_MONERO_WALLET_ADDRESS --merge-mine IP:port YOUR_WALLET_ADDRESS_ON_ANOTHER_BLOCKCHAIN
|
||||
```
|
||||
|
||||
- [Tari](https://www.tari.com/) uses their own gRPC API and requires a different command line:
|
||||
```
|
||||
p2pool.exe --wallet YOUR_MONERO_WALLET_ADDRESS --merge-mine tari://IP:port TARI_WALLET_ADDRESS
|
||||
```
|
||||
Merge mining is available for testing in Tari's [v1.0.0-pre.14 release](https://github.com/tari-project/tari/releases/tag/v1.0.0-pre.14) (Esmeralda testnet).
|
||||
### Tari merge mining
|
||||
|
||||
[Tari](https://www.tari.com/) uses their own gRPC API and requires a different command line:
|
||||
```
|
||||
./p2pool --wallet YOUR_MONERO_WALLET_ADDRESS --merge-mine tari://TARI_NODE_IP:18102 TARI_WALLET_ADDRESS
|
||||
```
|
||||
and on the Tari side
|
||||
```
|
||||
./minotari_node --grpc-enabled --mining-enabled
|
||||
```
|
||||
TARI_NODE_IP is 127.0.0.1 if you run both on the same machine (recommended).
|
||||
|
||||
Merge mining is available on Tari's mainnet:
|
||||
- Download [Tari suite](https://github.com/tari-project/tari/releases/latest) for your OS
|
||||
- Run Minotari node and wait until in synchronizes
|
||||
- Run Minotari console wallet to create a Tari wallet
|
||||
- Copy the interactive wallet address from the "Receive" tab of the wallet
|
||||
- Paste it into the P2Pool command line above
|
||||
- Everything is ready now to start merge mining Monero and Tari!
|
||||
|
||||
Note that Tari will be mined in solo mode (only full Tari blocks can be mined for now). This doesn't affect P2Pool payouts - they will stay the same.
|
||||
|
||||
### GNU/Linux
|
||||
|
||||
@@ -349,3 +365,13 @@ If you'd like to support further development of Monero P2Pool, you're welcome to
|
||||
```
|
||||
44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg
|
||||
```
|
||||
|
||||
Starting from v4.6, P2Pool will also have an ability to merge mine donations for the author.
|
||||
|
||||
Note that this will not affect your hashrate or payouts in any way. P2Pool will always (100% of the time) keep mining to your configured Monero wallet address, but it might also use the available merge mining capacity to donate to the author.
|
||||
|
||||
If you merge mine yourself, your settings will take priority.
|
||||
|
||||
The merge mining donation runs without a donation server - there is no "phoning home" to a server, everything is done through the P2Pool's network in a decentralized way.
|
||||
|
||||
To opt out of this, build P2Pool with `-DWITH_MERGE_MINING_DONATION=OFF` in cmake command line. Due to the architecture of the decentralized P2Pool network, your node will still relay donation messages to other nodes even if you opted out (but it will not process them).
|
||||
|
||||
+9
-1
@@ -17,12 +17,16 @@ 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-qual -Wlogical-op -Wundef -Wformat=2 -Wpointer-arith -Werror -Wno-error=inline -Wno-error=unused-function")
|
||||
set(WARNING_FLAGS "-Wall -Wextra -Wcast-qual -Wlogical-op -Wundef -Wformat=2 -Wpointer-arith -Werror -Wno-error=inline -Wno-error=unused-function -Wno-error=strict-overflow")
|
||||
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.5.0)
|
||||
set(WARNING_FLAGS "${WARNING_FLAGS} -Wstrict-overflow=2")
|
||||
endif()
|
||||
|
||||
if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15))
|
||||
set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-error=cpp")
|
||||
endif()
|
||||
|
||||
if (DISABLE_WARNINGS)
|
||||
set(WARNING_FLAGS "-w")
|
||||
endif()
|
||||
@@ -111,6 +115,10 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
|
||||
set(WARNING_FLAGS "-Wall -Wextra -Wno-unused-function -Wno-undefined-internal -Wunreachable-code-aggressive -Wmissing-prototypes -Wmissing-variable-declarations -Werror")
|
||||
|
||||
if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 20))
|
||||
set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-error=cpp")
|
||||
endif()
|
||||
|
||||
if (DISABLE_WARNINGS)
|
||||
set(WARNING_FLAGS "-w")
|
||||
endif()
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
@echo off
|
||||
"..\cppcheck-main\bin\cppcheck.exe" ../src/*.cpp -D__cppcheck__ -DSIZE_MAX=UINT64_MAX -DRAPIDJSON_ENDIAN=RAPIDJSON_LITTLEENDIAN -D_WIN32=1 -D_WIN64=1 -DWIN32=1 -D_WINDOWS=1 -DNDEBUG=1 -DWITH_GRPC=1 -DPROTOBUF_ENABLE_DEBUG_LOGGING_MAY_LEAK_PII=0 -DWITH_RANDOMX=1 -DWITH_UPNP=1 -DCURL_STATICLIB=1 -DWIN32_LEAN_AND_MEAN=1 -D_WIN32_WINNT=0x0600 -D_DISABLE_VECTOR_ANNOTATION=1 -D_DISABLE_STRING_ANNOTATION=1 -DZMQ_STATIC=1 -DHAVE_BITSCANREVERSE64=1 -DRAPIDJSON_PARSE_DEFAULT_FLAGS=kParseTrailingCommasFlag -DMINIUPNP_STATICLIB=1 -DCARES_STATICLIB=1 -DCMAKE_INTDIR="Release" -D__SSE2__=1 -D_MSC_VER=1929 --platform=win64 --std=c++17 --enable=all --inconclusive --inline-suppr --template="{file}:{line}:{id}{inconclusive: INCONCLUSIVE} {message}" --includes-file=includes.txt --suppressions-list=suppressions.txt --output-file=errors_full.txt --max-ctu-depth=3 --check-level=exhaustive --checkers-report=checkers_report.txt
|
||||
"..\cppcheck-main\bin\cppcheck.exe" ../src/*.cpp -D__cppcheck__ -DSIZE_MAX=UINT64_MAX -DRAPIDJSON_ENDIAN=RAPIDJSON_LITTLEENDIAN -D_WIN32=1 -D_WIN64=1 -DWIN32=1 -D_WINDOWS=1 -DNDEBUG=1 -DWITH_GRPC=1 -DPROTOBUF_ENABLE_DEBUG_LOGGING_MAY_LEAK_PII=0 -DWITH_RANDOMX=1 -DWITH_UPNP=1 -DWITH_TLS=1 -DWITH_MERGE_MINING_DONATION=1 -DCURL_STATICLIB=1 -DWIN32_LEAN_AND_MEAN=1 -D_WIN32_WINNT=0x0600 -D_DISABLE_VECTOR_ANNOTATION=1 -D_DISABLE_STRING_ANNOTATION=1 -DZMQ_STATIC=1 -DHAVE_BITSCANREVERSE64=1 -DRAPIDJSON_PARSE_DEFAULT_FLAGS=kParseTrailingCommasFlag -DMINIUPNP_STATICLIB=1 -DCARES_STATICLIB=1 -DCMAKE_INTDIR="Release" -D__SSE2__=1 -D_MSC_VER=1929 --platform=win64 --std=c++17 --enable=all --inconclusive --inline-suppr --template="{file}:{line}:{id}{inconclusive: INCONCLUSIVE} {message}" --includes-file=includes.txt --suppressions-list=suppressions.txt --output-file=errors_full.txt --max-ctu-depth=3 --check-level=exhaustive --checkers-report=checkers_report.txt
|
||||
|
||||
findstr /V /C:"external\src" errors_full.txt > errors_filtered0.txt
|
||||
findstr /V /C:":checkersReport" errors_filtered0.txt > errors_filtered.txt
|
||||
|
||||
+24
-11
@@ -22,6 +22,7 @@
|
||||
--in-peers N Maximum number of incoming connections for p2p server (any value between 10 and 450)
|
||||
--start-mining N Start built-in miner using N threads (any value between 1 and 64)
|
||||
--mini Connect to p2pool-mini sidechain. Note that it will also change default p2p port from 37889 to 37888
|
||||
--nano Connect to p2pool-nano sidechain. Note that it will also change default p2p port from 37889 to 37890
|
||||
--no-autodiff Disable automatic difficulty adjustment for miners connected to stratum (WARNING: incompatible with Nicehash and MRR)
|
||||
--rpc-login Specify username[:password] required for Monero RPC server
|
||||
--socks5 Specify IP:port of a SOCKS5 proxy to use for outgoing connections
|
||||
@@ -60,7 +61,7 @@ p2pool.exe --host 127.0.0.1 --host node.monerodevs.org --rpc-port 18089 --zmq-po
|
||||
|
||||
### Merge mining
|
||||
|
||||
Merge mining will be available in P2Pool after the fork on October 12th, 2024. Version 4.0 or newer is required to use it.
|
||||
Merge mining is available in P2Pool since the fork that happened on October 12th, 2024. Version 4.0 or newer is required to use it.
|
||||
|
||||
- Blockchains that will support [Merge mining RPC API](https://github.com/SChernykh/p2pool/blob/master/docs/MERGE_MINING.MD#proposed-rpc-api)
|
||||
- [Townforge](https://townforge.net/) supports it in their [tmp-mm branch](https://git.townforge.net/townforge/townforge/src/branch/tmp-mm) (not released yet)
|
||||
@@ -69,15 +70,27 @@ Merge mining will be available in P2Pool after the fork on October 12th, 2024. V
|
||||
p2pool.exe --wallet YOUR_MONERO_WALLET_ADDRESS --merge-mine IP:port YOUR_WALLET_ADDRESS_ON_ANOTHER_BLOCKCHAIN
|
||||
```
|
||||
|
||||
- [Tari](https://www.tari.com/) uses their own gRPC API and requires a different command line:
|
||||
```
|
||||
./p2pool --wallet YOUR_MONERO_WALLET_ADDRESS --merge-mine tari://IP:port TARI_WALLET_ADDRESS
|
||||
```
|
||||
and on the Tari side
|
||||
```
|
||||
./minotari_node --grpc-enabled --mining-enabled
|
||||
```
|
||||
Merge mining is available for testing in Tari's [latest release](https://github.com/tari-project/tari/releases) (Esmeralda testnet).
|
||||
### Tari merge mining
|
||||
|
||||
[Tari](https://www.tari.com/) uses their own gRPC API and requires a different command line:
|
||||
```
|
||||
./p2pool --wallet YOUR_MONERO_WALLET_ADDRESS --merge-mine tari://TARI_NODE_IP:18102 TARI_WALLET_ADDRESS
|
||||
```
|
||||
and on the Tari side
|
||||
```
|
||||
./minotari_node --grpc-enabled --mining-enabled
|
||||
```
|
||||
TARI_NODE_IP is 127.0.0.1 if you run both on the same machine (recommended).
|
||||
|
||||
Merge mining is available on Tari's mainnet:
|
||||
- Download [Tari suite](https://github.com/tari-project/tari/releases/latest) for your OS
|
||||
- Run Minotari node and wait until in synchronizes
|
||||
- Run Minotari console wallet to create a Tari wallet
|
||||
- Copy the interactive wallet address from the "Receive" tab of the wallet
|
||||
- Paste it into the P2Pool command line above
|
||||
- Everything is ready now to start merge mining Monero and Tari!
|
||||
|
||||
Note that Tari will be mined in solo mode (only full Tari blocks can be mined for now). This doesn't affect P2Pool payouts - they will stay the same.
|
||||
|
||||
### TLS
|
||||
|
||||
@@ -101,4 +114,4 @@ P2Pool supports certificate pinning on RPC-SSL connections via `--rpc-ssl-finger
|
||||
openssl x509 -in rpc_ssl.crt -pubkey -noout -inform pem | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
|
||||
```
|
||||
|
||||
By default, `rpc_ssl.crt` can be found in Monero data directory: `/home/username/.bitmonero/rpc_ssl.crt` on Linux and `C:\ProgramData\bitmonero\rpc_ssl.crt` on Windows.
|
||||
By default, `rpc_ssl.crt` can be found in Monero data directory: `/home/username/.bitmonero/rpc_ssl.crt` on Linux and `C:\ProgramData\bitmonero\rpc_ssl.crt` on Windows.
|
||||
|
||||
+786
-318
File diff suppressed because it is too large
Load Diff
+640
-70
@@ -172,6 +172,9 @@ extern ListAssetRegistrationsResponseDefaultTypeInternal _ListAssetRegistrations
|
||||
class ListHeadersRequest;
|
||||
struct ListHeadersRequestDefaultTypeInternal;
|
||||
extern ListHeadersRequestDefaultTypeInternal _ListHeadersRequest_default_instance_;
|
||||
class LivenessResult;
|
||||
struct LivenessResultDefaultTypeInternal;
|
||||
extern LivenessResultDefaultTypeInternal _LivenessResult_default_instance_;
|
||||
class MempoolStatsResponse;
|
||||
struct MempoolStatsResponseDefaultTypeInternal;
|
||||
extern MempoolStatsResponseDefaultTypeInternal _MempoolStatsResponse_default_instance_;
|
||||
@@ -583,20 +586,31 @@ class ValueAtHeightResponse final : public ::google::protobuf::Message
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
enum : int {
|
||||
kValueFieldNumber = 1,
|
||||
kHeightFieldNumber = 2,
|
||||
kCirculatingSupplyFieldNumber = 1,
|
||||
kSpendableSupplyFieldNumber = 2,
|
||||
kHeightFieldNumber = 3,
|
||||
};
|
||||
// uint64 value = 1;
|
||||
void clear_value() ;
|
||||
::uint64_t value() const;
|
||||
void set_value(::uint64_t value);
|
||||
// uint64 circulating_supply = 1;
|
||||
void clear_circulating_supply() ;
|
||||
::uint64_t circulating_supply() const;
|
||||
void set_circulating_supply(::uint64_t value);
|
||||
|
||||
private:
|
||||
::uint64_t _internal_value() const;
|
||||
void _internal_set_value(::uint64_t value);
|
||||
::uint64_t _internal_circulating_supply() const;
|
||||
void _internal_set_circulating_supply(::uint64_t value);
|
||||
|
||||
public:
|
||||
// uint64 height = 2;
|
||||
// uint64 spendable_supply = 2;
|
||||
void clear_spendable_supply() ;
|
||||
::uint64_t spendable_supply() const;
|
||||
void set_spendable_supply(::uint64_t value);
|
||||
|
||||
private:
|
||||
::uint64_t _internal_spendable_supply() const;
|
||||
void _internal_set_spendable_supply(::uint64_t value);
|
||||
|
||||
public:
|
||||
// uint64 height = 3;
|
||||
void clear_height() ;
|
||||
::uint64_t height() const;
|
||||
void set_height(::uint64_t value);
|
||||
@@ -611,7 +625,7 @@ class ValueAtHeightResponse final : public ::google::protobuf::Message
|
||||
class _Internal;
|
||||
friend class ::google::protobuf::internal::TcParser;
|
||||
static const ::google::protobuf::internal::TcParseTable<
|
||||
1, 2, 0,
|
||||
2, 3, 0,
|
||||
0, 2>
|
||||
_table_;
|
||||
friend class ::google::protobuf::MessageLite;
|
||||
@@ -627,7 +641,8 @@ class ValueAtHeightResponse final : public ::google::protobuf::Message
|
||||
::google::protobuf::Arena* arena);
|
||||
inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility,
|
||||
::google::protobuf::Arena* arena, const Impl_& from);
|
||||
::uint64_t value_;
|
||||
::uint64_t circulating_supply_;
|
||||
::uint64_t spendable_supply_;
|
||||
::uint64_t height_;
|
||||
mutable ::google::protobuf::internal::CachedSize _cached_size_;
|
||||
PROTOBUF_TSAN_DECLARE_MEMBER
|
||||
@@ -2291,8 +2306,9 @@ class NetworkDifficultyResponse final : public ::google::protobuf::Message
|
||||
kTimestampFieldNumber = 4,
|
||||
kPowAlgoFieldNumber = 5,
|
||||
kSha3XEstimatedHashRateFieldNumber = 6,
|
||||
kRandomxEstimatedHashRateFieldNumber = 7,
|
||||
kMoneroRandomxEstimatedHashRateFieldNumber = 7,
|
||||
kNumCoinbasesFieldNumber = 8,
|
||||
kTariRandomxEstimatedHashRateFieldNumber = 10,
|
||||
};
|
||||
// repeated bytes coinbase_extras = 9;
|
||||
int coinbase_extras_size() const;
|
||||
@@ -2382,14 +2398,14 @@ class NetworkDifficultyResponse final : public ::google::protobuf::Message
|
||||
void _internal_set_sha3x_estimated_hash_rate(::uint64_t value);
|
||||
|
||||
public:
|
||||
// uint64 randomx_estimated_hash_rate = 7;
|
||||
void clear_randomx_estimated_hash_rate() ;
|
||||
::uint64_t randomx_estimated_hash_rate() const;
|
||||
void set_randomx_estimated_hash_rate(::uint64_t value);
|
||||
// uint64 monero_randomx_estimated_hash_rate = 7;
|
||||
void clear_monero_randomx_estimated_hash_rate() ;
|
||||
::uint64_t monero_randomx_estimated_hash_rate() const;
|
||||
void set_monero_randomx_estimated_hash_rate(::uint64_t value);
|
||||
|
||||
private:
|
||||
::uint64_t _internal_randomx_estimated_hash_rate() const;
|
||||
void _internal_set_randomx_estimated_hash_rate(::uint64_t value);
|
||||
::uint64_t _internal_monero_randomx_estimated_hash_rate() const;
|
||||
void _internal_set_monero_randomx_estimated_hash_rate(::uint64_t value);
|
||||
|
||||
public:
|
||||
// uint64 num_coinbases = 8;
|
||||
@@ -2401,13 +2417,23 @@ class NetworkDifficultyResponse final : public ::google::protobuf::Message
|
||||
::uint64_t _internal_num_coinbases() const;
|
||||
void _internal_set_num_coinbases(::uint64_t value);
|
||||
|
||||
public:
|
||||
// uint64 tari_randomx_estimated_hash_rate = 10;
|
||||
void clear_tari_randomx_estimated_hash_rate() ;
|
||||
::uint64_t tari_randomx_estimated_hash_rate() const;
|
||||
void set_tari_randomx_estimated_hash_rate(::uint64_t value);
|
||||
|
||||
private:
|
||||
::uint64_t _internal_tari_randomx_estimated_hash_rate() const;
|
||||
void _internal_set_tari_randomx_estimated_hash_rate(::uint64_t value);
|
||||
|
||||
public:
|
||||
// @@protoc_insertion_point(class_scope:tari.rpc.NetworkDifficultyResponse)
|
||||
private:
|
||||
class _Internal;
|
||||
friend class ::google::protobuf::internal::TcParser;
|
||||
static const ::google::protobuf::internal::TcParseTable<
|
||||
4, 9, 0,
|
||||
4, 10, 0,
|
||||
0, 2>
|
||||
_table_;
|
||||
friend class ::google::protobuf::MessageLite;
|
||||
@@ -2430,8 +2456,9 @@ class NetworkDifficultyResponse final : public ::google::protobuf::Message
|
||||
::uint64_t timestamp_;
|
||||
::uint64_t pow_algo_;
|
||||
::uint64_t sha3x_estimated_hash_rate_;
|
||||
::uint64_t randomx_estimated_hash_rate_;
|
||||
::uint64_t monero_randomx_estimated_hash_rate_;
|
||||
::uint64_t num_coinbases_;
|
||||
::uint64_t tari_randomx_estimated_hash_rate_;
|
||||
mutable ::google::protobuf::internal::CachedSize _cached_size_;
|
||||
PROTOBUF_TSAN_DECLARE_MEMBER
|
||||
};
|
||||
@@ -2858,6 +2885,203 @@ class MempoolStatsResponse final : public ::google::protobuf::Message
|
||||
};
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
class LivenessResult final : public ::google::protobuf::Message
|
||||
/* @@protoc_insertion_point(class_definition:tari.rpc.LivenessResult) */ {
|
||||
public:
|
||||
inline LivenessResult() : LivenessResult(nullptr) {}
|
||||
~LivenessResult() override;
|
||||
template <typename = void>
|
||||
explicit PROTOBUF_CONSTEXPR LivenessResult(
|
||||
::google::protobuf::internal::ConstantInitialized);
|
||||
|
||||
inline LivenessResult(const LivenessResult& from) : LivenessResult(nullptr, from) {}
|
||||
inline LivenessResult(LivenessResult&& from) noexcept
|
||||
: LivenessResult(nullptr, std::move(from)) {}
|
||||
inline LivenessResult& operator=(const LivenessResult& from) {
|
||||
CopyFrom(from);
|
||||
return *this;
|
||||
}
|
||||
inline LivenessResult& operator=(LivenessResult&& from) noexcept {
|
||||
if (this == &from) return *this;
|
||||
if (GetArena() == from.GetArena()
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
&& GetArena() != nullptr
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_MOVE
|
||||
) {
|
||||
InternalSwap(&from);
|
||||
} else {
|
||||
CopyFrom(from);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const
|
||||
ABSL_ATTRIBUTE_LIFETIME_BOUND {
|
||||
return _internal_metadata_.unknown_fields<::google::protobuf::UnknownFieldSet>(::google::protobuf::UnknownFieldSet::default_instance);
|
||||
}
|
||||
inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields()
|
||||
ABSL_ATTRIBUTE_LIFETIME_BOUND {
|
||||
return _internal_metadata_.mutable_unknown_fields<::google::protobuf::UnknownFieldSet>();
|
||||
}
|
||||
|
||||
static const ::google::protobuf::Descriptor* descriptor() {
|
||||
return GetDescriptor();
|
||||
}
|
||||
static const ::google::protobuf::Descriptor* GetDescriptor() {
|
||||
return default_instance().GetMetadata().descriptor;
|
||||
}
|
||||
static const ::google::protobuf::Reflection* GetReflection() {
|
||||
return default_instance().GetMetadata().reflection;
|
||||
}
|
||||
static const LivenessResult& default_instance() {
|
||||
return *internal_default_instance();
|
||||
}
|
||||
static inline const LivenessResult* internal_default_instance() {
|
||||
return reinterpret_cast<const LivenessResult*>(
|
||||
&_LivenessResult_default_instance_);
|
||||
}
|
||||
static constexpr int kIndexInFileMessages = 57;
|
||||
friend void swap(LivenessResult& a, LivenessResult& b) { a.Swap(&b); }
|
||||
inline void Swap(LivenessResult* other) {
|
||||
if (other == this) return;
|
||||
#ifdef PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetArena() != nullptr && GetArena() == other->GetArena()) {
|
||||
#else // PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
if (GetArena() == other->GetArena()) {
|
||||
#endif // !PROTOBUF_FORCE_COPY_IN_SWAP
|
||||
InternalSwap(other);
|
||||
} else {
|
||||
::google::protobuf::internal::GenericSwap(this, other);
|
||||
}
|
||||
}
|
||||
void UnsafeArenaSwap(LivenessResult* other) {
|
||||
if (other == this) return;
|
||||
ABSL_DCHECK(GetArena() == other->GetArena());
|
||||
InternalSwap(other);
|
||||
}
|
||||
|
||||
// implements Message ----------------------------------------------
|
||||
|
||||
LivenessResult* New(::google::protobuf::Arena* arena = nullptr) const final {
|
||||
return ::google::protobuf::Message::DefaultConstruct<LivenessResult>(arena);
|
||||
}
|
||||
using ::google::protobuf::Message::CopyFrom;
|
||||
void CopyFrom(const LivenessResult& from);
|
||||
using ::google::protobuf::Message::MergeFrom;
|
||||
void MergeFrom(const LivenessResult& from) { LivenessResult::MergeImpl(*this, from); }
|
||||
|
||||
private:
|
||||
static void MergeImpl(
|
||||
::google::protobuf::MessageLite& to_msg,
|
||||
const ::google::protobuf::MessageLite& from_msg);
|
||||
|
||||
public:
|
||||
ABSL_ATTRIBUTE_REINITIALIZES void Clear() final;
|
||||
bool IsInitialized() const final;
|
||||
|
||||
::size_t ByteSizeLong() const final;
|
||||
const char* _InternalParse(const char* ptr, ::google::protobuf::internal::ParseContext* ctx) final;
|
||||
::uint8_t* _InternalSerialize(
|
||||
::uint8_t* target,
|
||||
::google::protobuf::io::EpsCopyOutputStream* stream) const final;
|
||||
int GetCachedSize() const { return _impl_._cached_size_.Get(); }
|
||||
|
||||
private:
|
||||
void SharedCtor(::google::protobuf::Arena* arena);
|
||||
void SharedDtor();
|
||||
void InternalSwap(LivenessResult* other);
|
||||
private:
|
||||
friend class ::google::protobuf::internal::AnyMetadata;
|
||||
static ::absl::string_view FullMessageName() { return "tari.rpc.LivenessResult"; }
|
||||
|
||||
protected:
|
||||
explicit LivenessResult(::google::protobuf::Arena* arena);
|
||||
LivenessResult(::google::protobuf::Arena* arena, const LivenessResult& from);
|
||||
LivenessResult(::google::protobuf::Arena* arena, LivenessResult&& from) noexcept
|
||||
: LivenessResult(arena) {
|
||||
*this = ::std::move(from);
|
||||
}
|
||||
const ::google::protobuf::MessageLite::ClassData* GetClassData()
|
||||
const final;
|
||||
|
||||
public:
|
||||
::google::protobuf::Metadata GetMetadata() const final;
|
||||
// nested types ----------------------------------------------------
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
enum : int {
|
||||
kPeerNodeIdFieldNumber = 1,
|
||||
kDiscoverLatencyFieldNumber = 2,
|
||||
kPingLatencyFieldNumber = 3,
|
||||
};
|
||||
// bytes peer_node_id = 1;
|
||||
void clear_peer_node_id() ;
|
||||
const std::string& peer_node_id() const;
|
||||
template <typename Arg_ = const std::string&, typename... Args_>
|
||||
void set_peer_node_id(Arg_&& arg, Args_... args);
|
||||
std::string* mutable_peer_node_id();
|
||||
PROTOBUF_NODISCARD std::string* release_peer_node_id();
|
||||
void set_allocated_peer_node_id(std::string* value);
|
||||
|
||||
private:
|
||||
const std::string& _internal_peer_node_id() const;
|
||||
inline PROTOBUF_ALWAYS_INLINE void _internal_set_peer_node_id(
|
||||
const std::string& value);
|
||||
std::string* _internal_mutable_peer_node_id();
|
||||
|
||||
public:
|
||||
// uint64 discover_latency = 2;
|
||||
void clear_discover_latency() ;
|
||||
::uint64_t discover_latency() const;
|
||||
void set_discover_latency(::uint64_t value);
|
||||
|
||||
private:
|
||||
::uint64_t _internal_discover_latency() const;
|
||||
void _internal_set_discover_latency(::uint64_t value);
|
||||
|
||||
public:
|
||||
// uint64 ping_latency = 3;
|
||||
void clear_ping_latency() ;
|
||||
::uint64_t ping_latency() const;
|
||||
void set_ping_latency(::uint64_t value);
|
||||
|
||||
private:
|
||||
::uint64_t _internal_ping_latency() const;
|
||||
void _internal_set_ping_latency(::uint64_t value);
|
||||
|
||||
public:
|
||||
// @@protoc_insertion_point(class_scope:tari.rpc.LivenessResult)
|
||||
private:
|
||||
class _Internal;
|
||||
friend class ::google::protobuf::internal::TcParser;
|
||||
static const ::google::protobuf::internal::TcParseTable<
|
||||
2, 3, 0,
|
||||
0, 2>
|
||||
_table_;
|
||||
friend class ::google::protobuf::MessageLite;
|
||||
friend class ::google::protobuf::Arena;
|
||||
template <typename T>
|
||||
friend class ::google::protobuf::Arena::InternalHelper;
|
||||
using InternalArenaConstructable_ = void;
|
||||
using DestructorSkippable_ = void;
|
||||
struct Impl_ {
|
||||
inline explicit constexpr Impl_(
|
||||
::google::protobuf::internal::ConstantInitialized) noexcept;
|
||||
inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility,
|
||||
::google::protobuf::Arena* arena);
|
||||
inline explicit Impl_(::google::protobuf::internal::InternalVisibility visibility,
|
||||
::google::protobuf::Arena* arena, const Impl_& from);
|
||||
::google::protobuf::internal::ArenaStringPtr peer_node_id_;
|
||||
::uint64_t discover_latency_;
|
||||
::uint64_t ping_latency_;
|
||||
mutable ::google::protobuf::internal::CachedSize _cached_size_;
|
||||
PROTOBUF_TSAN_DECLARE_MEMBER
|
||||
};
|
||||
union { Impl_ _impl_; };
|
||||
friend struct ::TableStruct_base_5fnode_2eproto;
|
||||
};
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
class ListHeadersRequest final : public ::google::protobuf::Message
|
||||
/* @@protoc_insertion_point(class_definition:tari.rpc.ListHeadersRequest) */ {
|
||||
public:
|
||||
@@ -8495,14 +8719,34 @@ class GetNetworkStateResponse final : public ::google::protobuf::Message
|
||||
|
||||
// accessors -------------------------------------------------------
|
||||
enum : int {
|
||||
kLivenessResultsFieldNumber = 9,
|
||||
kMetadataFieldNumber = 1,
|
||||
kBaseNodeStateFieldNumber = 3,
|
||||
kInitialSyncAchievedFieldNumber = 2,
|
||||
kFailedCheckpointsFieldNumber = 4,
|
||||
kRewardFieldNumber = 5,
|
||||
kSha3XEstimatedHashRateFieldNumber = 6,
|
||||
kRandomxEstimatedHashRateFieldNumber = 7,
|
||||
kMoneroRandomxEstimatedHashRateFieldNumber = 7,
|
||||
kNumConnectionsFieldNumber = 8,
|
||||
kTariRandomxEstimatedHashRateFieldNumber = 10,
|
||||
};
|
||||
// repeated .tari.rpc.LivenessResult liveness_results = 9;
|
||||
int liveness_results_size() const;
|
||||
private:
|
||||
int _internal_liveness_results_size() const;
|
||||
|
||||
public:
|
||||
void clear_liveness_results() ;
|
||||
::tari::rpc::LivenessResult* mutable_liveness_results(int index);
|
||||
::google::protobuf::RepeatedPtrField<::tari::rpc::LivenessResult>* mutable_liveness_results();
|
||||
|
||||
private:
|
||||
const ::google::protobuf::RepeatedPtrField<::tari::rpc::LivenessResult>& _internal_liveness_results() const;
|
||||
::google::protobuf::RepeatedPtrField<::tari::rpc::LivenessResult>* _internal_mutable_liveness_results();
|
||||
public:
|
||||
const ::tari::rpc::LivenessResult& liveness_results(int index) const;
|
||||
::tari::rpc::LivenessResult* add_liveness_results();
|
||||
const ::google::protobuf::RepeatedPtrField<::tari::rpc::LivenessResult>& liveness_results() const;
|
||||
// .tari.rpc.MetaData metadata = 1;
|
||||
bool has_metadata() const;
|
||||
void clear_metadata() ;
|
||||
@@ -8568,14 +8812,34 @@ class GetNetworkStateResponse final : public ::google::protobuf::Message
|
||||
void _internal_set_sha3x_estimated_hash_rate(::uint64_t value);
|
||||
|
||||
public:
|
||||
// uint64 randomx_estimated_hash_rate = 7;
|
||||
void clear_randomx_estimated_hash_rate() ;
|
||||
::uint64_t randomx_estimated_hash_rate() const;
|
||||
void set_randomx_estimated_hash_rate(::uint64_t value);
|
||||
// uint64 monero_randomx_estimated_hash_rate = 7;
|
||||
void clear_monero_randomx_estimated_hash_rate() ;
|
||||
::uint64_t monero_randomx_estimated_hash_rate() const;
|
||||
void set_monero_randomx_estimated_hash_rate(::uint64_t value);
|
||||
|
||||
private:
|
||||
::uint64_t _internal_randomx_estimated_hash_rate() const;
|
||||
void _internal_set_randomx_estimated_hash_rate(::uint64_t value);
|
||||
::uint64_t _internal_monero_randomx_estimated_hash_rate() const;
|
||||
void _internal_set_monero_randomx_estimated_hash_rate(::uint64_t value);
|
||||
|
||||
public:
|
||||
// uint64 num_connections = 8;
|
||||
void clear_num_connections() ;
|
||||
::uint64_t num_connections() const;
|
||||
void set_num_connections(::uint64_t value);
|
||||
|
||||
private:
|
||||
::uint64_t _internal_num_connections() const;
|
||||
void _internal_set_num_connections(::uint64_t value);
|
||||
|
||||
public:
|
||||
// uint64 tari_randomx_estimated_hash_rate = 10;
|
||||
void clear_tari_randomx_estimated_hash_rate() ;
|
||||
::uint64_t tari_randomx_estimated_hash_rate() const;
|
||||
void set_tari_randomx_estimated_hash_rate(::uint64_t value);
|
||||
|
||||
private:
|
||||
::uint64_t _internal_tari_randomx_estimated_hash_rate() const;
|
||||
void _internal_set_tari_randomx_estimated_hash_rate(::uint64_t value);
|
||||
|
||||
public:
|
||||
// @@protoc_insertion_point(class_scope:tari.rpc.GetNetworkStateResponse)
|
||||
@@ -8583,7 +8847,7 @@ class GetNetworkStateResponse final : public ::google::protobuf::Message
|
||||
class _Internal;
|
||||
friend class ::google::protobuf::internal::TcParser;
|
||||
static const ::google::protobuf::internal::TcParseTable<
|
||||
3, 7, 1,
|
||||
4, 10, 2,
|
||||
0, 2>
|
||||
_table_;
|
||||
friend class ::google::protobuf::MessageLite;
|
||||
@@ -8601,13 +8865,16 @@ class GetNetworkStateResponse final : public ::google::protobuf::Message
|
||||
::google::protobuf::Arena* arena, const Impl_& from);
|
||||
::google::protobuf::internal::HasBits<1> _has_bits_;
|
||||
mutable ::google::protobuf::internal::CachedSize _cached_size_;
|
||||
::google::protobuf::RepeatedPtrField< ::tari::rpc::LivenessResult > liveness_results_;
|
||||
::tari::rpc::MetaData* metadata_;
|
||||
int base_node_state_;
|
||||
bool initial_sync_achieved_;
|
||||
bool failed_checkpoints_;
|
||||
::uint64_t reward_;
|
||||
::uint64_t sha3x_estimated_hash_rate_;
|
||||
::uint64_t randomx_estimated_hash_rate_;
|
||||
::uint64_t monero_randomx_estimated_hash_rate_;
|
||||
::uint64_t num_connections_;
|
||||
::uint64_t tari_randomx_estimated_hash_rate_;
|
||||
PROTOBUF_TSAN_DECLARE_MEMBER
|
||||
};
|
||||
union { Impl_ _impl_; };
|
||||
@@ -11085,6 +11352,7 @@ class GetNewBlockResult final : public ::google::protobuf::Message
|
||||
kBlockHashFieldNumber = 1,
|
||||
kMergeMiningHashFieldNumber = 3,
|
||||
kTariUniqueIdFieldNumber = 4,
|
||||
kVmKeyFieldNumber = 6,
|
||||
kBlockFieldNumber = 2,
|
||||
kMinerDataFieldNumber = 5,
|
||||
};
|
||||
@@ -11135,6 +11403,22 @@ class GetNewBlockResult final : public ::google::protobuf::Message
|
||||
const std::string& value);
|
||||
std::string* _internal_mutable_tari_unique_id();
|
||||
|
||||
public:
|
||||
// bytes vm_key = 6;
|
||||
void clear_vm_key() ;
|
||||
const std::string& vm_key() const;
|
||||
template <typename Arg_ = const std::string&, typename... Args_>
|
||||
void set_vm_key(Arg_&& arg, Args_... args);
|
||||
std::string* mutable_vm_key();
|
||||
PROTOBUF_NODISCARD std::string* release_vm_key();
|
||||
void set_allocated_vm_key(std::string* value);
|
||||
|
||||
private:
|
||||
const std::string& _internal_vm_key() const;
|
||||
inline PROTOBUF_ALWAYS_INLINE void _internal_set_vm_key(
|
||||
const std::string& value);
|
||||
std::string* _internal_mutable_vm_key();
|
||||
|
||||
public:
|
||||
// .tari.rpc.Block block = 2;
|
||||
bool has_block() const;
|
||||
@@ -11171,7 +11455,7 @@ class GetNewBlockResult final : public ::google::protobuf::Message
|
||||
class _Internal;
|
||||
friend class ::google::protobuf::internal::TcParser;
|
||||
static const ::google::protobuf::internal::TcParseTable<
|
||||
3, 5, 2,
|
||||
3, 6, 2,
|
||||
0, 2>
|
||||
_table_;
|
||||
friend class ::google::protobuf::MessageLite;
|
||||
@@ -11192,6 +11476,7 @@ class GetNewBlockResult final : public ::google::protobuf::Message
|
||||
::google::protobuf::internal::ArenaStringPtr block_hash_;
|
||||
::google::protobuf::internal::ArenaStringPtr merge_mining_hash_;
|
||||
::google::protobuf::internal::ArenaStringPtr tari_unique_id_;
|
||||
::google::protobuf::internal::ArenaStringPtr vm_key_;
|
||||
::tari::rpc::Block* block_;
|
||||
::tari::rpc::MinerData* miner_data_;
|
||||
PROTOBUF_TSAN_DECLARE_MEMBER
|
||||
@@ -14188,26 +14473,48 @@ inline void NetworkDifficultyResponse::_internal_set_sha3x_estimated_hash_rate(:
|
||||
_impl_.sha3x_estimated_hash_rate_ = value;
|
||||
}
|
||||
|
||||
// uint64 randomx_estimated_hash_rate = 7;
|
||||
inline void NetworkDifficultyResponse::clear_randomx_estimated_hash_rate() {
|
||||
// uint64 monero_randomx_estimated_hash_rate = 7;
|
||||
inline void NetworkDifficultyResponse::clear_monero_randomx_estimated_hash_rate() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.randomx_estimated_hash_rate_ = ::uint64_t{0u};
|
||||
_impl_.monero_randomx_estimated_hash_rate_ = ::uint64_t{0u};
|
||||
}
|
||||
inline ::uint64_t NetworkDifficultyResponse::randomx_estimated_hash_rate() const {
|
||||
// @@protoc_insertion_point(field_get:tari.rpc.NetworkDifficultyResponse.randomx_estimated_hash_rate)
|
||||
return _internal_randomx_estimated_hash_rate();
|
||||
inline ::uint64_t NetworkDifficultyResponse::monero_randomx_estimated_hash_rate() const {
|
||||
// @@protoc_insertion_point(field_get:tari.rpc.NetworkDifficultyResponse.monero_randomx_estimated_hash_rate)
|
||||
return _internal_monero_randomx_estimated_hash_rate();
|
||||
}
|
||||
inline void NetworkDifficultyResponse::set_randomx_estimated_hash_rate(::uint64_t value) {
|
||||
_internal_set_randomx_estimated_hash_rate(value);
|
||||
// @@protoc_insertion_point(field_set:tari.rpc.NetworkDifficultyResponse.randomx_estimated_hash_rate)
|
||||
inline void NetworkDifficultyResponse::set_monero_randomx_estimated_hash_rate(::uint64_t value) {
|
||||
_internal_set_monero_randomx_estimated_hash_rate(value);
|
||||
// @@protoc_insertion_point(field_set:tari.rpc.NetworkDifficultyResponse.monero_randomx_estimated_hash_rate)
|
||||
}
|
||||
inline ::uint64_t NetworkDifficultyResponse::_internal_randomx_estimated_hash_rate() const {
|
||||
inline ::uint64_t NetworkDifficultyResponse::_internal_monero_randomx_estimated_hash_rate() const {
|
||||
PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race);
|
||||
return _impl_.randomx_estimated_hash_rate_;
|
||||
return _impl_.monero_randomx_estimated_hash_rate_;
|
||||
}
|
||||
inline void NetworkDifficultyResponse::_internal_set_randomx_estimated_hash_rate(::uint64_t value) {
|
||||
inline void NetworkDifficultyResponse::_internal_set_monero_randomx_estimated_hash_rate(::uint64_t value) {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.randomx_estimated_hash_rate_ = value;
|
||||
_impl_.monero_randomx_estimated_hash_rate_ = value;
|
||||
}
|
||||
|
||||
// uint64 tari_randomx_estimated_hash_rate = 10;
|
||||
inline void NetworkDifficultyResponse::clear_tari_randomx_estimated_hash_rate() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.tari_randomx_estimated_hash_rate_ = ::uint64_t{0u};
|
||||
}
|
||||
inline ::uint64_t NetworkDifficultyResponse::tari_randomx_estimated_hash_rate() const {
|
||||
// @@protoc_insertion_point(field_get:tari.rpc.NetworkDifficultyResponse.tari_randomx_estimated_hash_rate)
|
||||
return _internal_tari_randomx_estimated_hash_rate();
|
||||
}
|
||||
inline void NetworkDifficultyResponse::set_tari_randomx_estimated_hash_rate(::uint64_t value) {
|
||||
_internal_set_tari_randomx_estimated_hash_rate(value);
|
||||
// @@protoc_insertion_point(field_set:tari.rpc.NetworkDifficultyResponse.tari_randomx_estimated_hash_rate)
|
||||
}
|
||||
inline ::uint64_t NetworkDifficultyResponse::_internal_tari_randomx_estimated_hash_rate() const {
|
||||
PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race);
|
||||
return _impl_.tari_randomx_estimated_hash_rate_;
|
||||
}
|
||||
inline void NetworkDifficultyResponse::_internal_set_tari_randomx_estimated_hash_rate(::uint64_t value) {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.tari_randomx_estimated_hash_rate_ = value;
|
||||
}
|
||||
|
||||
// uint64 num_coinbases = 8;
|
||||
@@ -14338,29 +14645,51 @@ NetworkDifficultyResponse::_internal_mutable_coinbase_extras() {
|
||||
|
||||
// ValueAtHeightResponse
|
||||
|
||||
// uint64 value = 1;
|
||||
inline void ValueAtHeightResponse::clear_value() {
|
||||
// uint64 circulating_supply = 1;
|
||||
inline void ValueAtHeightResponse::clear_circulating_supply() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.value_ = ::uint64_t{0u};
|
||||
_impl_.circulating_supply_ = ::uint64_t{0u};
|
||||
}
|
||||
inline ::uint64_t ValueAtHeightResponse::value() const {
|
||||
// @@protoc_insertion_point(field_get:tari.rpc.ValueAtHeightResponse.value)
|
||||
return _internal_value();
|
||||
inline ::uint64_t ValueAtHeightResponse::circulating_supply() const {
|
||||
// @@protoc_insertion_point(field_get:tari.rpc.ValueAtHeightResponse.circulating_supply)
|
||||
return _internal_circulating_supply();
|
||||
}
|
||||
inline void ValueAtHeightResponse::set_value(::uint64_t value) {
|
||||
_internal_set_value(value);
|
||||
// @@protoc_insertion_point(field_set:tari.rpc.ValueAtHeightResponse.value)
|
||||
inline void ValueAtHeightResponse::set_circulating_supply(::uint64_t value) {
|
||||
_internal_set_circulating_supply(value);
|
||||
// @@protoc_insertion_point(field_set:tari.rpc.ValueAtHeightResponse.circulating_supply)
|
||||
}
|
||||
inline ::uint64_t ValueAtHeightResponse::_internal_value() const {
|
||||
inline ::uint64_t ValueAtHeightResponse::_internal_circulating_supply() const {
|
||||
PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race);
|
||||
return _impl_.value_;
|
||||
return _impl_.circulating_supply_;
|
||||
}
|
||||
inline void ValueAtHeightResponse::_internal_set_value(::uint64_t value) {
|
||||
inline void ValueAtHeightResponse::_internal_set_circulating_supply(::uint64_t value) {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.value_ = value;
|
||||
_impl_.circulating_supply_ = value;
|
||||
}
|
||||
|
||||
// uint64 height = 2;
|
||||
// uint64 spendable_supply = 2;
|
||||
inline void ValueAtHeightResponse::clear_spendable_supply() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.spendable_supply_ = ::uint64_t{0u};
|
||||
}
|
||||
inline ::uint64_t ValueAtHeightResponse::spendable_supply() const {
|
||||
// @@protoc_insertion_point(field_get:tari.rpc.ValueAtHeightResponse.spendable_supply)
|
||||
return _internal_spendable_supply();
|
||||
}
|
||||
inline void ValueAtHeightResponse::set_spendable_supply(::uint64_t value) {
|
||||
_internal_set_spendable_supply(value);
|
||||
// @@protoc_insertion_point(field_set:tari.rpc.ValueAtHeightResponse.spendable_supply)
|
||||
}
|
||||
inline ::uint64_t ValueAtHeightResponse::_internal_spendable_supply() const {
|
||||
PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race);
|
||||
return _impl_.spendable_supply_;
|
||||
}
|
||||
inline void ValueAtHeightResponse::_internal_set_spendable_supply(::uint64_t value) {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.spendable_supply_ = value;
|
||||
}
|
||||
|
||||
// uint64 height = 3;
|
||||
inline void ValueAtHeightResponse::clear_height() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.height_ = ::uint64_t{0u};
|
||||
@@ -15973,6 +16302,56 @@ inline void GetNewBlockResult::set_allocated_miner_data(::tari::rpc::MinerData*
|
||||
// @@protoc_insertion_point(field_set_allocated:tari.rpc.GetNewBlockResult.miner_data)
|
||||
}
|
||||
|
||||
// bytes vm_key = 6;
|
||||
inline void GetNewBlockResult::clear_vm_key() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.vm_key_.ClearToEmpty();
|
||||
}
|
||||
inline const std::string& GetNewBlockResult::vm_key() const
|
||||
ABSL_ATTRIBUTE_LIFETIME_BOUND {
|
||||
// @@protoc_insertion_point(field_get:tari.rpc.GetNewBlockResult.vm_key)
|
||||
return _internal_vm_key();
|
||||
}
|
||||
template <typename Arg_, typename... Args_>
|
||||
inline PROTOBUF_ALWAYS_INLINE void GetNewBlockResult::set_vm_key(Arg_&& arg,
|
||||
Args_... args) {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.vm_key_.SetBytes(static_cast<Arg_&&>(arg), args..., GetArena());
|
||||
// @@protoc_insertion_point(field_set:tari.rpc.GetNewBlockResult.vm_key)
|
||||
}
|
||||
inline std::string* GetNewBlockResult::mutable_vm_key() ABSL_ATTRIBUTE_LIFETIME_BOUND {
|
||||
std::string* _s = _internal_mutable_vm_key();
|
||||
// @@protoc_insertion_point(field_mutable:tari.rpc.GetNewBlockResult.vm_key)
|
||||
return _s;
|
||||
}
|
||||
inline const std::string& GetNewBlockResult::_internal_vm_key() const {
|
||||
PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race);
|
||||
return _impl_.vm_key_.Get();
|
||||
}
|
||||
inline void GetNewBlockResult::_internal_set_vm_key(const std::string& value) {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.vm_key_.Set(value, GetArena());
|
||||
}
|
||||
inline std::string* GetNewBlockResult::_internal_mutable_vm_key() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
return _impl_.vm_key_.Mutable( GetArena());
|
||||
}
|
||||
inline std::string* GetNewBlockResult::release_vm_key() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
// @@protoc_insertion_point(field_release:tari.rpc.GetNewBlockResult.vm_key)
|
||||
return _impl_.vm_key_.Release();
|
||||
}
|
||||
inline void GetNewBlockResult::set_allocated_vm_key(std::string* value) {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.vm_key_.SetAllocated(value, GetArena());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
if (_impl_.vm_key_.IsDefault()) {
|
||||
_impl_.vm_key_.Set("", GetArena());
|
||||
}
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
// @@protoc_insertion_point(field_set_allocated:tari.rpc.GetNewBlockResult.vm_key)
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
// GetNewBlockBlobResult
|
||||
@@ -18368,26 +18747,217 @@ inline void GetNetworkStateResponse::_internal_set_sha3x_estimated_hash_rate(::u
|
||||
_impl_.sha3x_estimated_hash_rate_ = value;
|
||||
}
|
||||
|
||||
// uint64 randomx_estimated_hash_rate = 7;
|
||||
inline void GetNetworkStateResponse::clear_randomx_estimated_hash_rate() {
|
||||
// uint64 monero_randomx_estimated_hash_rate = 7;
|
||||
inline void GetNetworkStateResponse::clear_monero_randomx_estimated_hash_rate() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.randomx_estimated_hash_rate_ = ::uint64_t{0u};
|
||||
_impl_.monero_randomx_estimated_hash_rate_ = ::uint64_t{0u};
|
||||
}
|
||||
inline ::uint64_t GetNetworkStateResponse::randomx_estimated_hash_rate() const {
|
||||
// @@protoc_insertion_point(field_get:tari.rpc.GetNetworkStateResponse.randomx_estimated_hash_rate)
|
||||
return _internal_randomx_estimated_hash_rate();
|
||||
inline ::uint64_t GetNetworkStateResponse::monero_randomx_estimated_hash_rate() const {
|
||||
// @@protoc_insertion_point(field_get:tari.rpc.GetNetworkStateResponse.monero_randomx_estimated_hash_rate)
|
||||
return _internal_monero_randomx_estimated_hash_rate();
|
||||
}
|
||||
inline void GetNetworkStateResponse::set_randomx_estimated_hash_rate(::uint64_t value) {
|
||||
_internal_set_randomx_estimated_hash_rate(value);
|
||||
// @@protoc_insertion_point(field_set:tari.rpc.GetNetworkStateResponse.randomx_estimated_hash_rate)
|
||||
inline void GetNetworkStateResponse::set_monero_randomx_estimated_hash_rate(::uint64_t value) {
|
||||
_internal_set_monero_randomx_estimated_hash_rate(value);
|
||||
// @@protoc_insertion_point(field_set:tari.rpc.GetNetworkStateResponse.monero_randomx_estimated_hash_rate)
|
||||
}
|
||||
inline ::uint64_t GetNetworkStateResponse::_internal_randomx_estimated_hash_rate() const {
|
||||
inline ::uint64_t GetNetworkStateResponse::_internal_monero_randomx_estimated_hash_rate() const {
|
||||
PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race);
|
||||
return _impl_.randomx_estimated_hash_rate_;
|
||||
return _impl_.monero_randomx_estimated_hash_rate_;
|
||||
}
|
||||
inline void GetNetworkStateResponse::_internal_set_randomx_estimated_hash_rate(::uint64_t value) {
|
||||
inline void GetNetworkStateResponse::_internal_set_monero_randomx_estimated_hash_rate(::uint64_t value) {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.randomx_estimated_hash_rate_ = value;
|
||||
_impl_.monero_randomx_estimated_hash_rate_ = value;
|
||||
}
|
||||
|
||||
// uint64 tari_randomx_estimated_hash_rate = 10;
|
||||
inline void GetNetworkStateResponse::clear_tari_randomx_estimated_hash_rate() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.tari_randomx_estimated_hash_rate_ = ::uint64_t{0u};
|
||||
}
|
||||
inline ::uint64_t GetNetworkStateResponse::tari_randomx_estimated_hash_rate() const {
|
||||
// @@protoc_insertion_point(field_get:tari.rpc.GetNetworkStateResponse.tari_randomx_estimated_hash_rate)
|
||||
return _internal_tari_randomx_estimated_hash_rate();
|
||||
}
|
||||
inline void GetNetworkStateResponse::set_tari_randomx_estimated_hash_rate(::uint64_t value) {
|
||||
_internal_set_tari_randomx_estimated_hash_rate(value);
|
||||
// @@protoc_insertion_point(field_set:tari.rpc.GetNetworkStateResponse.tari_randomx_estimated_hash_rate)
|
||||
}
|
||||
inline ::uint64_t GetNetworkStateResponse::_internal_tari_randomx_estimated_hash_rate() const {
|
||||
PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race);
|
||||
return _impl_.tari_randomx_estimated_hash_rate_;
|
||||
}
|
||||
inline void GetNetworkStateResponse::_internal_set_tari_randomx_estimated_hash_rate(::uint64_t value) {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.tari_randomx_estimated_hash_rate_ = value;
|
||||
}
|
||||
|
||||
// uint64 num_connections = 8;
|
||||
inline void GetNetworkStateResponse::clear_num_connections() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.num_connections_ = ::uint64_t{0u};
|
||||
}
|
||||
inline ::uint64_t GetNetworkStateResponse::num_connections() const {
|
||||
// @@protoc_insertion_point(field_get:tari.rpc.GetNetworkStateResponse.num_connections)
|
||||
return _internal_num_connections();
|
||||
}
|
||||
inline void GetNetworkStateResponse::set_num_connections(::uint64_t value) {
|
||||
_internal_set_num_connections(value);
|
||||
// @@protoc_insertion_point(field_set:tari.rpc.GetNetworkStateResponse.num_connections)
|
||||
}
|
||||
inline ::uint64_t GetNetworkStateResponse::_internal_num_connections() const {
|
||||
PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race);
|
||||
return _impl_.num_connections_;
|
||||
}
|
||||
inline void GetNetworkStateResponse::_internal_set_num_connections(::uint64_t value) {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.num_connections_ = value;
|
||||
}
|
||||
|
||||
// repeated .tari.rpc.LivenessResult liveness_results = 9;
|
||||
inline int GetNetworkStateResponse::_internal_liveness_results_size() const {
|
||||
return _internal_liveness_results().size();
|
||||
}
|
||||
inline int GetNetworkStateResponse::liveness_results_size() const {
|
||||
return _internal_liveness_results_size();
|
||||
}
|
||||
inline void GetNetworkStateResponse::clear_liveness_results() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.liveness_results_.Clear();
|
||||
}
|
||||
inline ::tari::rpc::LivenessResult* GetNetworkStateResponse::mutable_liveness_results(int index)
|
||||
ABSL_ATTRIBUTE_LIFETIME_BOUND {
|
||||
// @@protoc_insertion_point(field_mutable:tari.rpc.GetNetworkStateResponse.liveness_results)
|
||||
return _internal_mutable_liveness_results()->Mutable(index);
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField<::tari::rpc::LivenessResult>* GetNetworkStateResponse::mutable_liveness_results()
|
||||
ABSL_ATTRIBUTE_LIFETIME_BOUND {
|
||||
// @@protoc_insertion_point(field_mutable_list:tari.rpc.GetNetworkStateResponse.liveness_results)
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
return _internal_mutable_liveness_results();
|
||||
}
|
||||
inline const ::tari::rpc::LivenessResult& GetNetworkStateResponse::liveness_results(int index) const
|
||||
ABSL_ATTRIBUTE_LIFETIME_BOUND {
|
||||
// @@protoc_insertion_point(field_get:tari.rpc.GetNetworkStateResponse.liveness_results)
|
||||
return _internal_liveness_results().Get(index);
|
||||
}
|
||||
inline ::tari::rpc::LivenessResult* GetNetworkStateResponse::add_liveness_results() ABSL_ATTRIBUTE_LIFETIME_BOUND {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
::tari::rpc::LivenessResult* _add = _internal_mutable_liveness_results()->Add();
|
||||
// @@protoc_insertion_point(field_add:tari.rpc.GetNetworkStateResponse.liveness_results)
|
||||
return _add;
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField<::tari::rpc::LivenessResult>& GetNetworkStateResponse::liveness_results() const
|
||||
ABSL_ATTRIBUTE_LIFETIME_BOUND {
|
||||
// @@protoc_insertion_point(field_list:tari.rpc.GetNetworkStateResponse.liveness_results)
|
||||
return _internal_liveness_results();
|
||||
}
|
||||
inline const ::google::protobuf::RepeatedPtrField<::tari::rpc::LivenessResult>&
|
||||
GetNetworkStateResponse::_internal_liveness_results() const {
|
||||
PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race);
|
||||
return _impl_.liveness_results_;
|
||||
}
|
||||
inline ::google::protobuf::RepeatedPtrField<::tari::rpc::LivenessResult>*
|
||||
GetNetworkStateResponse::_internal_mutable_liveness_results() {
|
||||
PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race);
|
||||
return &_impl_.liveness_results_;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
// LivenessResult
|
||||
|
||||
// bytes peer_node_id = 1;
|
||||
inline void LivenessResult::clear_peer_node_id() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.peer_node_id_.ClearToEmpty();
|
||||
}
|
||||
inline const std::string& LivenessResult::peer_node_id() const
|
||||
ABSL_ATTRIBUTE_LIFETIME_BOUND {
|
||||
// @@protoc_insertion_point(field_get:tari.rpc.LivenessResult.peer_node_id)
|
||||
return _internal_peer_node_id();
|
||||
}
|
||||
template <typename Arg_, typename... Args_>
|
||||
inline PROTOBUF_ALWAYS_INLINE void LivenessResult::set_peer_node_id(Arg_&& arg,
|
||||
Args_... args) {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.peer_node_id_.SetBytes(static_cast<Arg_&&>(arg), args..., GetArena());
|
||||
// @@protoc_insertion_point(field_set:tari.rpc.LivenessResult.peer_node_id)
|
||||
}
|
||||
inline std::string* LivenessResult::mutable_peer_node_id() ABSL_ATTRIBUTE_LIFETIME_BOUND {
|
||||
std::string* _s = _internal_mutable_peer_node_id();
|
||||
// @@protoc_insertion_point(field_mutable:tari.rpc.LivenessResult.peer_node_id)
|
||||
return _s;
|
||||
}
|
||||
inline const std::string& LivenessResult::_internal_peer_node_id() const {
|
||||
PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race);
|
||||
return _impl_.peer_node_id_.Get();
|
||||
}
|
||||
inline void LivenessResult::_internal_set_peer_node_id(const std::string& value) {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.peer_node_id_.Set(value, GetArena());
|
||||
}
|
||||
inline std::string* LivenessResult::_internal_mutable_peer_node_id() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
return _impl_.peer_node_id_.Mutable( GetArena());
|
||||
}
|
||||
inline std::string* LivenessResult::release_peer_node_id() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
// @@protoc_insertion_point(field_release:tari.rpc.LivenessResult.peer_node_id)
|
||||
return _impl_.peer_node_id_.Release();
|
||||
}
|
||||
inline void LivenessResult::set_allocated_peer_node_id(std::string* value) {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.peer_node_id_.SetAllocated(value, GetArena());
|
||||
#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
if (_impl_.peer_node_id_.IsDefault()) {
|
||||
_impl_.peer_node_id_.Set("", GetArena());
|
||||
}
|
||||
#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
|
||||
// @@protoc_insertion_point(field_set_allocated:tari.rpc.LivenessResult.peer_node_id)
|
||||
}
|
||||
|
||||
// uint64 discover_latency = 2;
|
||||
inline void LivenessResult::clear_discover_latency() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.discover_latency_ = ::uint64_t{0u};
|
||||
}
|
||||
inline ::uint64_t LivenessResult::discover_latency() const {
|
||||
// @@protoc_insertion_point(field_get:tari.rpc.LivenessResult.discover_latency)
|
||||
return _internal_discover_latency();
|
||||
}
|
||||
inline void LivenessResult::set_discover_latency(::uint64_t value) {
|
||||
_internal_set_discover_latency(value);
|
||||
// @@protoc_insertion_point(field_set:tari.rpc.LivenessResult.discover_latency)
|
||||
}
|
||||
inline ::uint64_t LivenessResult::_internal_discover_latency() const {
|
||||
PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race);
|
||||
return _impl_.discover_latency_;
|
||||
}
|
||||
inline void LivenessResult::_internal_set_discover_latency(::uint64_t value) {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.discover_latency_ = value;
|
||||
}
|
||||
|
||||
// uint64 ping_latency = 3;
|
||||
inline void LivenessResult::clear_ping_latency() {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.ping_latency_ = ::uint64_t{0u};
|
||||
}
|
||||
inline ::uint64_t LivenessResult::ping_latency() const {
|
||||
// @@protoc_insertion_point(field_get:tari.rpc.LivenessResult.ping_latency)
|
||||
return _internal_ping_latency();
|
||||
}
|
||||
inline void LivenessResult::set_ping_latency(::uint64_t value) {
|
||||
_internal_set_ping_latency(value);
|
||||
// @@protoc_insertion_point(field_set:tari.rpc.LivenessResult.ping_latency)
|
||||
}
|
||||
inline ::uint64_t LivenessResult::_internal_ping_latency() const {
|
||||
PROTOBUF_TSAN_READ(&_impl_._tsan_detect_race);
|
||||
return _impl_.ping_latency_;
|
||||
}
|
||||
inline void LivenessResult::_internal_set_ping_latency(::uint64_t value) {
|
||||
PROTOBUF_TSAN_WRITE(&_impl_._tsan_detect_race);
|
||||
_impl_.ping_latency_ = value;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
+21
-4
@@ -218,15 +218,17 @@ message NetworkDifficultyResponse {
|
||||
uint64 timestamp = 4;
|
||||
uint64 pow_algo = 5;
|
||||
uint64 sha3x_estimated_hash_rate = 6;
|
||||
uint64 randomx_estimated_hash_rate = 7;
|
||||
uint64 monero_randomx_estimated_hash_rate = 7;
|
||||
uint64 tari_randomx_estimated_hash_rate = 10;
|
||||
uint64 num_coinbases = 8;
|
||||
repeated bytes coinbase_extras = 9;
|
||||
}
|
||||
|
||||
// A generic single value response for a specific height
|
||||
message ValueAtHeightResponse {
|
||||
uint64 value= 1;
|
||||
uint64 height = 2;
|
||||
uint64 circulating_supply = 1;
|
||||
uint64 spendable_supply = 2;
|
||||
uint64 height = 3;
|
||||
}
|
||||
|
||||
// A generic uint value
|
||||
@@ -382,6 +384,7 @@ message GetNewBlockResult{
|
||||
bytes merge_mining_hash =3;
|
||||
bytes tari_unique_id =4;
|
||||
MinerData miner_data = 5;
|
||||
bytes vm_key = 6;
|
||||
}
|
||||
|
||||
// This is the message that is returned for a miner after it asks for a new block.
|
||||
@@ -539,6 +542,20 @@ message GetNetworkStateResponse {
|
||||
// estimate sha3x hash rate
|
||||
uint64 sha3x_estimated_hash_rate = 6;
|
||||
// estimate randomx hash rate
|
||||
uint64 randomx_estimated_hash_rate = 7;
|
||||
uint64 monero_randomx_estimated_hash_rate = 7;
|
||||
uint64 tari_randomx_estimated_hash_rate = 10;
|
||||
// number of connections
|
||||
uint64 num_connections = 8;
|
||||
//liveness results
|
||||
repeated LivenessResult liveness_results = 9;
|
||||
}
|
||||
|
||||
message LivenessResult{
|
||||
// node id
|
||||
bytes peer_node_id = 1;
|
||||
// time to discover
|
||||
uint64 discover_latency = 2;
|
||||
// Dial latency
|
||||
uint64 ping_latency = 3;
|
||||
}
|
||||
|
||||
|
||||
+21
-20
@@ -371,22 +371,22 @@ const char descriptor_table_protodef_block_2eproto[] ABSL_ATTRIBUTE_SECTION_VARI
|
||||
"tal_script_offset\030\017 \001(\014\022\031\n\021validator_nod"
|
||||
"e_mr\030\020 \001(\014\022\033\n\023validator_node_size\030\021 \001(\004\""
|
||||
"1\n\013ProofOfWork\022\020\n\010pow_algo\030\001 \001(\004\022\020\n\010pow_"
|
||||
"data\030\004 \001(\014\"o\n\007PowAlgo\022,\n\010pow_algo\030\001 \001(\0162"
|
||||
"\032.tari.rpc.PowAlgo.PowAlgos\"6\n\010PowAlgos\022"
|
||||
"\025\n\021POW_ALGOS_RANDOMX\020\000\022\023\n\017POW_ALGOS_SHA3"
|
||||
"X\020\001\"U\n\005Block\022%\n\006header\030\001 \001(\0132\025.tari.rpc."
|
||||
"BlockHeader\022%\n\004body\030\002 \001(\0132\027.tari.rpc.Agg"
|
||||
"regateBody\"H\n\017HistoricalBlock\022\025\n\rconfirm"
|
||||
"ations\030\001 \001(\004\022\036\n\005block\030\002 \001(\0132\017.tari.rpc.B"
|
||||
"lock\"\252\001\n\026NewBlockHeaderTemplate\022\017\n\007versi"
|
||||
"on\030\001 \001(\r\022\016\n\006height\030\002 \001(\004\022\021\n\tprev_hash\030\003 "
|
||||
"\001(\014\022\033\n\023total_kernel_offset\030\004 \001(\014\022\"\n\003pow\030"
|
||||
"\005 \001(\0132\025.tari.rpc.ProofOfWork\022\033\n\023total_sc"
|
||||
"ript_offset\030\007 \001(\014\"\207\001\n\020NewBlockTemplate\0220"
|
||||
"\n\006header\030\001 \001(\0132 .tari.rpc.NewBlockHeader"
|
||||
"Template\022%\n\004body\030\002 \001(\0132\027.tari.rpc.Aggreg"
|
||||
"ateBody\022\032\n\022is_mempool_in_sync\030\003 \001(\010b\006pro"
|
||||
"to3"
|
||||
"data\030\004 \001(\014\"\210\001\n\007PowAlgo\022,\n\010pow_algo\030\001 \001(\016"
|
||||
"2\032.tari.rpc.PowAlgo.PowAlgos\"O\n\010PowAlgos"
|
||||
"\022\026\n\022POW_ALGOS_RANDOMXM\020\000\022\023\n\017POW_ALGOS_SH"
|
||||
"A3X\020\001\022\026\n\022POW_ALGOS_RANDOMXT\020\002\"U\n\005Block\022%"
|
||||
"\n\006header\030\001 \001(\0132\025.tari.rpc.BlockHeader\022%\n"
|
||||
"\004body\030\002 \001(\0132\027.tari.rpc.AggregateBody\"H\n\017"
|
||||
"HistoricalBlock\022\025\n\rconfirmations\030\001 \001(\004\022\036"
|
||||
"\n\005block\030\002 \001(\0132\017.tari.rpc.Block\"\252\001\n\026NewBl"
|
||||
"ockHeaderTemplate\022\017\n\007version\030\001 \001(\r\022\016\n\006he"
|
||||
"ight\030\002 \001(\004\022\021\n\tprev_hash\030\003 \001(\014\022\033\n\023total_k"
|
||||
"ernel_offset\030\004 \001(\014\022\"\n\003pow\030\005 \001(\0132\025.tari.r"
|
||||
"pc.ProofOfWork\022\033\n\023total_script_offset\030\007 "
|
||||
"\001(\014\"\207\001\n\020NewBlockTemplate\0220\n\006header\030\001 \001(\013"
|
||||
"2 .tari.rpc.NewBlockHeaderTemplate\022%\n\004bo"
|
||||
"dy\030\002 \001(\0132\027.tari.rpc.AggregateBody\022\032\n\022is_"
|
||||
"mempool_in_sync\030\003 \001(\010b\006proto3"
|
||||
};
|
||||
static const ::_pbi::DescriptorTable* const descriptor_table_block_2eproto_deps[1] =
|
||||
{
|
||||
@@ -396,7 +396,7 @@ static ::absl::once_flag descriptor_table_block_2eproto_once;
|
||||
const ::_pbi::DescriptorTable descriptor_table_block_2eproto = {
|
||||
false,
|
||||
false,
|
||||
1083,
|
||||
1109,
|
||||
descriptor_table_protodef_block_2eproto,
|
||||
"block.proto",
|
||||
&descriptor_table_block_2eproto_once,
|
||||
@@ -432,15 +432,16 @@ const ::google::protobuf::EnumDescriptor* PowAlgo_PowAlgos_descriptor() {
|
||||
return file_level_enum_descriptors_block_2eproto[0];
|
||||
}
|
||||
PROTOBUF_CONSTINIT const uint32_t PowAlgo_PowAlgos_internal_data_[] = {
|
||||
131072u, 0u, };
|
||||
196608u, 0u, };
|
||||
bool PowAlgo_PowAlgos_IsValid(int value) {
|
||||
return 0 <= value && value <= 1;
|
||||
return 0 <= value && value <= 2;
|
||||
}
|
||||
#if (__cplusplus < 201703) && \
|
||||
(!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
|
||||
|
||||
constexpr PowAlgo_PowAlgos PowAlgo::POW_ALGOS_RANDOMX;
|
||||
constexpr PowAlgo_PowAlgos PowAlgo::POW_ALGOS_RANDOMXM;
|
||||
constexpr PowAlgo_PowAlgos PowAlgo::POW_ALGOS_SHA3X;
|
||||
constexpr PowAlgo_PowAlgos PowAlgo::POW_ALGOS_RANDOMXT;
|
||||
constexpr PowAlgo_PowAlgos PowAlgo::PowAlgos_MIN;
|
||||
constexpr PowAlgo_PowAlgos PowAlgo::PowAlgos_MAX;
|
||||
constexpr int PowAlgo::PowAlgos_ARRAYSIZE;
|
||||
|
||||
+7
-5
@@ -84,8 +84,9 @@ namespace protobuf {
|
||||
namespace tari {
|
||||
namespace rpc {
|
||||
enum PowAlgo_PowAlgos : int {
|
||||
PowAlgo_PowAlgos_POW_ALGOS_RANDOMX = 0,
|
||||
PowAlgo_PowAlgos_POW_ALGOS_RANDOMXM = 0,
|
||||
PowAlgo_PowAlgos_POW_ALGOS_SHA3X = 1,
|
||||
PowAlgo_PowAlgos_POW_ALGOS_RANDOMXT = 2,
|
||||
PowAlgo_PowAlgos_PowAlgo_PowAlgos_INT_MIN_SENTINEL_DO_NOT_USE_ =
|
||||
std::numeric_limits<::int32_t>::min(),
|
||||
PowAlgo_PowAlgos_PowAlgo_PowAlgos_INT_MAX_SENTINEL_DO_NOT_USE_ =
|
||||
@@ -95,8 +96,8 @@ enum PowAlgo_PowAlgos : int {
|
||||
bool PowAlgo_PowAlgos_IsValid(int value);
|
||||
extern const uint32_t PowAlgo_PowAlgos_internal_data_[];
|
||||
constexpr PowAlgo_PowAlgos PowAlgo_PowAlgos_PowAlgos_MIN = static_cast<PowAlgo_PowAlgos>(0);
|
||||
constexpr PowAlgo_PowAlgos PowAlgo_PowAlgos_PowAlgos_MAX = static_cast<PowAlgo_PowAlgos>(1);
|
||||
constexpr int PowAlgo_PowAlgos_PowAlgos_ARRAYSIZE = 1 + 1;
|
||||
constexpr PowAlgo_PowAlgos PowAlgo_PowAlgos_PowAlgos_MAX = static_cast<PowAlgo_PowAlgos>(2);
|
||||
constexpr int PowAlgo_PowAlgos_PowAlgos_ARRAYSIZE = 2 + 1;
|
||||
const ::google::protobuf::EnumDescriptor*
|
||||
PowAlgo_PowAlgos_descriptor();
|
||||
template <typename T>
|
||||
@@ -109,7 +110,7 @@ const std::string& PowAlgo_PowAlgos_Name(T value) {
|
||||
template <>
|
||||
inline const std::string& PowAlgo_PowAlgos_Name(PowAlgo_PowAlgos value) {
|
||||
return ::google::protobuf::internal::NameOfDenseEnum<PowAlgo_PowAlgos_descriptor,
|
||||
0, 1>(
|
||||
0, 2>(
|
||||
static_cast<int>(value));
|
||||
}
|
||||
inline bool PowAlgo_PowAlgos_Parse(absl::string_view name, PowAlgo_PowAlgos* value) {
|
||||
@@ -430,8 +431,9 @@ class PowAlgo final : public ::google::protobuf::Message
|
||||
::google::protobuf::Metadata GetMetadata() const final;
|
||||
// nested types ----------------------------------------------------
|
||||
using PowAlgos = PowAlgo_PowAlgos;
|
||||
static constexpr PowAlgos POW_ALGOS_RANDOMX = PowAlgo_PowAlgos_POW_ALGOS_RANDOMX;
|
||||
static constexpr PowAlgos POW_ALGOS_RANDOMXM = PowAlgo_PowAlgos_POW_ALGOS_RANDOMXM;
|
||||
static constexpr PowAlgos POW_ALGOS_SHA3X = PowAlgo_PowAlgos_POW_ALGOS_SHA3X;
|
||||
static constexpr PowAlgos POW_ALGOS_RANDOMXT = PowAlgo_PowAlgos_POW_ALGOS_RANDOMXT;
|
||||
static inline bool PowAlgos_IsValid(int value) {
|
||||
return PowAlgo_PowAlgos_IsValid(value);
|
||||
}
|
||||
|
||||
+2
-1
@@ -80,8 +80,9 @@ message ProofOfWork {
|
||||
message PowAlgo {
|
||||
// The permitted pow algorithms
|
||||
enum PowAlgos {
|
||||
POW_ALGOS_RANDOMX = 0; // Accessible as `grpc::pow_algo::PowAlgos::Randomx`
|
||||
POW_ALGOS_RANDOMXM = 0; // Accessible as `grpc::pow_algo::PowAlgos::RandomxM`
|
||||
POW_ALGOS_SHA3X = 1; // Accessible as `grpc::pow_algo::PowAlgos::Sha3x`
|
||||
POW_ALGOS_RANDOMXT = 2; // Accessible as `grpc::pow_algo::PowAlgos::RandomxT`
|
||||
}
|
||||
// The pow algo to use
|
||||
PowAlgos pow_algo = 1;
|
||||
|
||||
Vendored
+1
-1
Submodule external/src/cppzmq updated: a371495a91...87ceb2cf17
Vendored
+11
-3
@@ -21,6 +21,14 @@
|
||||
#include <memory.h>
|
||||
|
||||
/****************************** MACROS ******************************/
|
||||
typedef struct {
|
||||
uint8_t data[64];
|
||||
uint32_t datalen;
|
||||
uint32_t padding;
|
||||
uint64_t bitlen;
|
||||
uint32_t state[8];
|
||||
} SHA256_CTX;
|
||||
|
||||
#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b))))
|
||||
#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
|
||||
|
||||
@@ -85,7 +93,7 @@ static void sha256_transform(SHA256_CTX *ctx, const uint8_t* data)
|
||||
ctx->state[7] += h;
|
||||
}
|
||||
|
||||
void sha256_init(SHA256_CTX *ctx)
|
||||
static void sha256_init(SHA256_CTX *ctx)
|
||||
{
|
||||
ctx->datalen = 0;
|
||||
ctx->bitlen = 0;
|
||||
@@ -99,7 +107,7 @@ void sha256_init(SHA256_CTX *ctx)
|
||||
ctx->state[7] = 0x5be0cd19;
|
||||
}
|
||||
|
||||
void sha256_update(SHA256_CTX *ctx, const uint8_t* data, uint32_t len)
|
||||
static void sha256_update(SHA256_CTX *ctx, const uint8_t* data, uint32_t len)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
@@ -114,7 +122,7 @@ void sha256_update(SHA256_CTX *ctx, const uint8_t* data, uint32_t len)
|
||||
}
|
||||
}
|
||||
|
||||
void sha256_final(SHA256_CTX *ctx, uint8_t* hash)
|
||||
static void sha256_final(SHA256_CTX *ctx, uint8_t* hash)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
|
||||
Vendored
-16
@@ -16,22 +16,6 @@ extern "C" {
|
||||
/*************************** HEADER FILES ***************************/
|
||||
#include <stdint.h>
|
||||
|
||||
/****************************** MACROS ******************************/
|
||||
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
|
||||
|
||||
typedef struct {
|
||||
uint8_t data[64];
|
||||
uint32_t datalen;
|
||||
uint32_t padding;
|
||||
uint64_t bitlen;
|
||||
uint32_t state[8];
|
||||
} SHA256_CTX;
|
||||
|
||||
/*********************** FUNCTION DECLARATIONS **********************/
|
||||
void sha256_init(SHA256_CTX *ctx);
|
||||
void sha256_update(SHA256_CTX *ctx, const uint8_t* data, uint32_t len);
|
||||
void sha256_final(SHA256_CTX *ctx, uint8_t* hash);
|
||||
|
||||
void sha256(const void* data, uint32_t len, uint8_t* hash);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Vendored
+1
-1
Submodule external/src/curl updated: 06c37f3218...0ab4f7e0e2
Vendored
+1
-1
Submodule external/src/miniupnp updated: 7e28c9f8af...f667d71d6b
@@ -612,6 +612,20 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const
|
||||
m_poolBlockTemplate->m_auxChains = data.aux_chains;
|
||||
m_poolBlockTemplate->m_auxNonce = data.aux_nonce;
|
||||
|
||||
m_poolBlockTemplate->m_mergeMiningExtra.clear();
|
||||
|
||||
for (const AuxChainData& c : data.aux_chains) {
|
||||
std::vector<uint8_t> v;
|
||||
v.reserve(HASH_SIZE + 16);
|
||||
|
||||
v.assign(c.data.h, c.data.h + HASH_SIZE);
|
||||
|
||||
writeVarint(c.difficulty.lo, v);
|
||||
writeVarint(c.difficulty.hi, v);
|
||||
|
||||
m_poolBlockTemplate->m_mergeMiningExtra.emplace(c.unique_id, std::move(v));
|
||||
}
|
||||
|
||||
init_merge_mining_merkle_proof();
|
||||
|
||||
const std::vector<uint8_t> sidechain_data = m_poolBlockTemplate->serialize_sidechain_data();
|
||||
|
||||
@@ -111,8 +111,10 @@ CurlContext::CurlContext(const std::string& address, int port, const std::string
|
||||
(void)ssl_fingerprint;
|
||||
#endif
|
||||
|
||||
const bool is_v6 = (address.find(':') != std::string::npos);
|
||||
|
||||
log::Stream s(buf);
|
||||
s << protocol << address << ':' << port;
|
||||
s << protocol << (is_v6 ? "[" : "") << address << (is_v6 ? "]:" : ":") << port;
|
||||
|
||||
if (!m_req.empty() && (m_req.front() == '/')) {
|
||||
s << m_req.c_str() << '\0';
|
||||
|
||||
@@ -62,6 +62,7 @@ void p2pool_usage()
|
||||
"--in-peers N Maximum number of incoming connections for p2p server (any value between 10 and 450)\n"
|
||||
"--start-mining N Start built-in miner using N threads (any value between 1 and 64)\n"
|
||||
"--mini Connect to p2pool-mini sidechain. Note that it will also change default p2p port from %d to %d\n"
|
||||
"--nano Connect to p2pool-nano sidechain. Note that it will also change default p2p port from %d to %d\n"
|
||||
"--no-autodiff Disable automatic difficulty adjustment for miners connected to stratum (WARNING: incompatible with Nicehash and MRR)\n"
|
||||
"--rpc-login Specify username[:password] required for Monero RPC server\n"
|
||||
"--socks5 Specify IP:port of a SOCKS5 proxy to use for outgoing connections\n"
|
||||
@@ -88,6 +89,8 @@ void p2pool_usage()
|
||||
p2pool::log::MAX_GLOBAL_LOG_LEVEL,
|
||||
p2pool::DEFAULT_P2P_PORT,
|
||||
p2pool::DEFAULT_P2P_PORT_MINI,
|
||||
p2pool::DEFAULT_P2P_PORT,
|
||||
p2pool::DEFAULT_P2P_PORT_NANO,
|
||||
#ifdef _WIN32
|
||||
"p2pool.exe"
|
||||
#else
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace p2pool {
|
||||
|
||||
class p2pool;
|
||||
class BlockTemplate;
|
||||
struct PoolBlock;
|
||||
|
||||
class IMergeMiningClient
|
||||
{
|
||||
@@ -38,7 +39,8 @@ public:
|
||||
virtual ~IMergeMiningClient() {}
|
||||
|
||||
[[nodiscard]] virtual bool get_params(ChainParameters& out_params) const = 0;
|
||||
virtual void submit_solution(const BlockTemplate* block_tpl, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path) = 0;
|
||||
virtual void on_external_block(const PoolBlock& block) = 0;
|
||||
virtual void submit_solution(const std::vector<uint8_t>& coinbase_merkle_proof, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path) = 0;
|
||||
|
||||
virtual void print_status() const = 0;
|
||||
};
|
||||
|
||||
@@ -287,7 +287,7 @@ bool MergeMiningClientJSON_RPC::parse_merge_mining_get_aux_block(const char* dat
|
||||
return true;
|
||||
}
|
||||
|
||||
void MergeMiningClientJSON_RPC::submit_solution(const BlockTemplate* /*block_tpl*/, const uint8_t (&/*hashing_blob*/)[128], size_t /*nonce_offset*/, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path)
|
||||
void MergeMiningClientJSON_RPC::submit_solution(const std::vector<uint8_t>& /*coinbase_merkle_proof*/, const uint8_t (&/*hashing_blob*/)[128], size_t /*nonce_offset*/, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path)
|
||||
{
|
||||
ReadLock lock(m_lock);
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
namespace p2pool {
|
||||
|
||||
class p2pool;
|
||||
struct PoolBlock;
|
||||
|
||||
class MergeMiningClientJSON_RPC : public IMergeMiningClient
|
||||
{
|
||||
@@ -30,7 +31,8 @@ public:
|
||||
~MergeMiningClientJSON_RPC() override;
|
||||
|
||||
bool get_params(ChainParameters& out_params) const override;
|
||||
void submit_solution(const BlockTemplate* block_tpl, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path) override;
|
||||
void on_external_block(const PoolBlock& /*block*/) override {}
|
||||
void submit_solution(const std::vector<uint8_t>& coinbase_merkle_proof, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path) override;
|
||||
|
||||
void print_status() const override;
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@
|
||||
#include "params.h"
|
||||
#include "block_template.h"
|
||||
#include "keccak.h"
|
||||
#include "pool_block.h"
|
||||
#include "merkle.h"
|
||||
#include "side_chain.h"
|
||||
|
||||
LOG_CATEGORY(MergeMiningClientTari)
|
||||
|
||||
@@ -31,6 +34,8 @@ namespace p2pool {
|
||||
|
||||
MergeMiningClientTari::MergeMiningClientTari(p2pool* pool, std::string host, const std::string& wallet)
|
||||
: m_chainParams{}
|
||||
, m_previousAuxHashes{}
|
||||
, m_previousAuxHashesIndex(0)
|
||||
, m_auxWallet(wallet)
|
||||
, m_pool(pool)
|
||||
, m_tariJobParams{}
|
||||
@@ -79,7 +84,17 @@ MergeMiningClientTari::MergeMiningClientTari(p2pool* pool, std::string host, con
|
||||
log::Stream s(buf);
|
||||
s << "127.0.0.1:" << m_server->external_listen_port();
|
||||
|
||||
m_TariNode = new BaseNode::Stub(grpc::CreateChannel(buf, grpc::InsecureChannelCredentials()));
|
||||
grpc::ChannelArguments cArgs;
|
||||
|
||||
cArgs.SetInt(GRPC_ARG_INITIAL_RECONNECT_BACKOFF_MS, 1000);
|
||||
|
||||
cArgs.SetInt(GRPC_ARG_MIN_RECONNECT_BACKOFF_MS, 1000);
|
||||
cArgs.SetInt(GRPC_ARG_MAX_RECONNECT_BACKOFF_MS, 10000);
|
||||
|
||||
cArgs.SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, -1);
|
||||
cArgs.SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, -1);
|
||||
|
||||
m_TariNode = new BaseNode::Stub(grpc::CreateCustomChannel(buf, grpc::InsecureChannelCredentials(), cArgs));
|
||||
|
||||
uv_mutex_init_checked(&m_workerLock);
|
||||
uv_cond_init_checked(&m_workerCond);
|
||||
@@ -127,7 +142,191 @@ bool MergeMiningClientTari::get_params(ChainParameters& out_params) const
|
||||
return true;
|
||||
}
|
||||
|
||||
void MergeMiningClientTari::submit_solution(const BlockTemplate* block_tpl, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path)
|
||||
void MergeMiningClientTari::on_external_block(const PoolBlock& block)
|
||||
{
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
// The rest of the code is needed only when this node is sending donation messages
|
||||
if (m_pool->params().m_authorKeyFile.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if (block.m_transactions.empty() || block.m_hashingBlob.empty() || (block.m_hashingBlob.size() > 128)) {
|
||||
LOGWARN(3, "on_external_block: sanity check failed - " << block.m_transactions.size() << " transactions, hashing blob size = " << block.m_hashingBlob.size());
|
||||
return;
|
||||
}
|
||||
|
||||
ChainParameters chain_params;
|
||||
uint64_t previous_aux_hashes[NUM_PREVIOUS_HASHES];
|
||||
{
|
||||
ReadLock lock(m_chainParamsLock);
|
||||
|
||||
chain_params = m_chainParams;
|
||||
memcpy(previous_aux_hashes, m_previousAuxHashes, sizeof(m_previousAuxHashes));
|
||||
}
|
||||
|
||||
// Don't continue if our aux chain is not there
|
||||
if (block.m_mergeMiningExtra.find(chain_params.aux_id) == block.m_mergeMiningExtra.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<hash> aux_ids;
|
||||
std::vector<AuxChainData> aux_chains;
|
||||
|
||||
// All aux chains in this block + the P2Pool sidechain
|
||||
aux_ids.reserve(block.m_mergeMiningExtra.size() + 1);
|
||||
|
||||
// All aux chains in this block
|
||||
aux_chains.reserve(block.m_mergeMiningExtra.size());
|
||||
|
||||
for (const auto& i : block.m_mergeMiningExtra) {
|
||||
const std::vector<uint8_t>& v = i.second;
|
||||
|
||||
const uint8_t* p = v.data();
|
||||
const uint8_t* e = v.data() + v.size();
|
||||
|
||||
if (p + HASH_SIZE > e) {
|
||||
LOGWARN(3, "on_external_block: sanity check failed - invalid merge mining extra data " << '1');
|
||||
return;
|
||||
}
|
||||
|
||||
hash data;
|
||||
memcpy(data.h, p, HASH_SIZE);
|
||||
p += HASH_SIZE;
|
||||
|
||||
difficulty_type diff;
|
||||
p = readVarint(p, e, diff.lo);
|
||||
if (!p) {
|
||||
LOGWARN(3, "on_external_block: sanity check failed - invalid merge mining extra data " << '2');
|
||||
return;
|
||||
}
|
||||
|
||||
p = readVarint(p, e, diff.hi);
|
||||
if (!p) {
|
||||
LOGWARN(3, "on_external_block: sanity check failed - invalid merge mining extra data " << '3');
|
||||
return;
|
||||
}
|
||||
|
||||
// If it's our aux chain, check that it's the same job and that there is enough PoW
|
||||
if (i.first == chain_params.aux_id) {
|
||||
if ((data != chain_params.aux_hash) || (diff != chain_params.aux_diff)) {
|
||||
const uint64_t* a = previous_aux_hashes;
|
||||
const uint64_t* b = previous_aux_hashes + NUM_PREVIOUS_HASHES;
|
||||
|
||||
if (std::find(a, b, *data.u64()) == b) {
|
||||
LOGINFO(4, "External aux job solution found, but it's for another miner");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
LOGINFO(4, "External aux job solution found, but it's stale");
|
||||
}
|
||||
}
|
||||
|
||||
if (!diff.check_pow(block.m_powHash)) {
|
||||
LOGINFO(4, "External aux job solution found, but it doesn't have enough PoW (block diff = " << block.m_difficulty << ", Tari diff = " << diff << ')');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
aux_ids.emplace_back(i.first);
|
||||
aux_chains.emplace_back(i.first, data, diff);
|
||||
}
|
||||
|
||||
aux_ids.emplace_back(m_pool->side_chain().consensus_hash());
|
||||
|
||||
LOGINFO(0, log::LightGreen() << "External aux job solution found. Processing it!");
|
||||
|
||||
// coinbase_merkle_proof
|
||||
|
||||
std::vector<std::vector<hash>> tree;
|
||||
|
||||
merkle_hash_full_tree(block.m_transactions, tree);
|
||||
|
||||
std::vector<hash> proof;
|
||||
uint32_t path;
|
||||
|
||||
if (!get_merkle_proof(tree, block.m_transactions[0], proof, path)) {
|
||||
LOGWARN(3, "on_external_block: get_merkle_proof failed for coinbase transaction");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> coinbase_merkle_proof;
|
||||
for (const hash& h : proof) {
|
||||
coinbase_merkle_proof.insert(coinbase_merkle_proof.end(), h.h, h.h + HASH_SIZE);
|
||||
}
|
||||
|
||||
// hashing_blob
|
||||
|
||||
uint8_t hashing_blob[128] = {};
|
||||
memcpy(hashing_blob, block.m_hashingBlob.data(), block.m_hashingBlob.size());
|
||||
|
||||
// nonce_offset and blob
|
||||
|
||||
size_t header_size = 0;
|
||||
const std::vector<uint8_t> blob = block.serialize_mainchain_data(&header_size);
|
||||
|
||||
if (header_size <= NONCE_SIZE) {
|
||||
LOGWARN(3, "on_external_block: invalid header_size");
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t nonce_offset = static_cast<uint32_t>(header_size - NONCE_SIZE);
|
||||
|
||||
// aux_merkle_proof, aux_merkle_proof_path
|
||||
|
||||
std::vector<hash> aux_merkle_proof;
|
||||
uint32_t aux_merkle_proof_path = 0;
|
||||
|
||||
const hash sidechain_id = block.m_sidechainId;
|
||||
const uint32_t n_aux_chains = static_cast<uint32_t>(block.m_mergeMiningExtra.size() + 1);
|
||||
|
||||
std::vector<hash> hashes(n_aux_chains);
|
||||
|
||||
uint32_t aux_nonce;
|
||||
if (!find_aux_nonce(aux_ids, aux_nonce, 1000)) {
|
||||
LOGWARN(3, "on_external_block: failed to find aux_nonce");
|
||||
return;
|
||||
}
|
||||
|
||||
for (const AuxChainData& aux_data : aux_chains) {
|
||||
const uint32_t aux_slot = get_aux_slot(aux_data.unique_id, aux_nonce, n_aux_chains);
|
||||
|
||||
if (!hashes[aux_slot].empty()) {
|
||||
LOGWARN(3, "on_external_block: found an incorrect aux_nonce " << '1');
|
||||
return;
|
||||
}
|
||||
|
||||
hashes[aux_slot] = aux_data.data;
|
||||
}
|
||||
|
||||
const uint32_t aux_slot = get_aux_slot(m_pool->side_chain().consensus_hash(), aux_nonce, n_aux_chains);
|
||||
|
||||
if (!hashes[aux_slot].empty()) {
|
||||
LOGWARN(3, "on_external_block: found an incorrect aux_nonce " << '2');
|
||||
return;
|
||||
}
|
||||
|
||||
hashes[aux_slot] = sidechain_id;
|
||||
|
||||
merkle_hash_full_tree(hashes, tree);
|
||||
|
||||
if (tree.empty() || tree.back().empty() || (tree.back().front() != block.m_merkleRoot)) {
|
||||
LOGWARN(3, "on_external_block: merkle root didn't match");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!get_merkle_proof(tree, chain_params.aux_hash, aux_merkle_proof, aux_merkle_proof_path)) {
|
||||
LOGWARN(3, "on_external_block: get_merkle_proof failed for the aux hash");
|
||||
return;
|
||||
}
|
||||
|
||||
submit_solution(coinbase_merkle_proof, hashing_blob, nonce_offset, block.m_seed, blob, aux_merkle_proof, aux_merkle_proof_path);
|
||||
#else // WITH_MERGE_MINING_DONATION
|
||||
(void) block;
|
||||
#endif // WITH_MERGE_MINING_DONATION
|
||||
}
|
||||
|
||||
void MergeMiningClientTari::submit_solution(const std::vector<uint8_t>& coinbase_merkle_proof, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path)
|
||||
{
|
||||
Block block;
|
||||
{
|
||||
@@ -136,7 +335,7 @@ void MergeMiningClientTari::submit_solution(const BlockTemplate* block_tpl, cons
|
||||
}
|
||||
|
||||
ProofOfWork* pow = block.mutable_header()->mutable_pow();
|
||||
pow->set_pow_algo(PowAlgo_PowAlgos_POW_ALGOS_RANDOMX);
|
||||
pow->set_pow_algo(PowAlgo_PowAlgos_POW_ALGOS_RANDOMXM);
|
||||
|
||||
{
|
||||
std::string data;
|
||||
@@ -164,8 +363,6 @@ void MergeMiningClientTari::submit_solution(const BlockTemplate* block_tpl, cons
|
||||
data.append(reinterpret_cast<const char*>(hashing_blob + nonce_offset + sizeof(uint32_t)), HASH_SIZE);
|
||||
|
||||
// Coinbase transaction's Merkle proof
|
||||
const std::vector<uint8_t> coinbase_merkle_proof = block_tpl->get_coinbase_merkle_proof();
|
||||
|
||||
// Number of hashes in the proof (varint, but an O(logN) proof will never get bigger than 127)
|
||||
data.append(1, static_cast<char>(coinbase_merkle_proof.size() / HASH_SIZE));
|
||||
|
||||
@@ -247,7 +444,35 @@ void MergeMiningClientTari::submit_solution(const BlockTemplate* block_tpl, cons
|
||||
uv_work_t req;
|
||||
MergeMiningClientTari* client;
|
||||
Block block;
|
||||
} *work = new Work{ {}, this, std::move(block) };
|
||||
|
||||
FORCEINLINE Work(MergeMiningClientTari* c, Block&& b) : req{}, client(c), block(std::move(b)) {}
|
||||
|
||||
void process() const
|
||||
{
|
||||
grpc::ClientContext ctx;
|
||||
SubmitBlockResponse response;
|
||||
|
||||
const grpc::Status status = client->m_TariNode->SubmitBlock(&ctx, block, &response);
|
||||
|
||||
if (!status.ok()) {
|
||||
LOGWARN(4, "SubmitBlock failed: " << status.error_message());
|
||||
if (!status.error_details().empty()) {
|
||||
LOGWARN(4, "SubmitBlock failed: " << status.error_details());
|
||||
}
|
||||
}
|
||||
else {
|
||||
const std::string& h = response.block_hash();
|
||||
LOGINFO(0, log::LightGreen() << "Mined Tari block " << log::hex_buf(h.data(), h.size()) << " at height " << block.header().height());
|
||||
}
|
||||
}
|
||||
} *work = new Work(this, std::move(block));
|
||||
|
||||
if (!is_main_thread()) {
|
||||
LOGINFO(5, "Running SubmitBlock in the current thread because uv_default_loop can only be used in the main thread");
|
||||
work->process();
|
||||
delete work;
|
||||
return;
|
||||
}
|
||||
|
||||
work->req.data = work;
|
||||
|
||||
@@ -255,23 +480,7 @@ void MergeMiningClientTari::submit_solution(const BlockTemplate* block_tpl, cons
|
||||
[](uv_work_t* req)
|
||||
{
|
||||
BACKGROUND_JOB_START(MergeMiningClientTari::submit_solution);
|
||||
|
||||
grpc::ClientContext ctx;
|
||||
SubmitBlockResponse response;
|
||||
|
||||
const Work* w = reinterpret_cast<Work*>(req->data);
|
||||
const grpc::Status status = w->client->m_TariNode->SubmitBlock(&ctx, w->block, &response);
|
||||
|
||||
if (!status.ok()) {
|
||||
LOGWARN(5, "SubmitBlock failed: " << status.error_message());
|
||||
if (!status.error_details().empty()) {
|
||||
LOGWARN(5, "SubmitBlock failed: " << status.error_details());
|
||||
}
|
||||
}
|
||||
else {
|
||||
const std::string& h = response.block_hash();
|
||||
LOGINFO(0, log::LightGreen() << "Mined Tari block " << log::hex_buf(h.data(), h.size()) << " at height " << w->block.header().height());
|
||||
}
|
||||
reinterpret_cast<Work*>(req->data)->process();
|
||||
},
|
||||
[](uv_work_t* req, int /*status*/)
|
||||
{
|
||||
@@ -338,98 +547,142 @@ void MergeMiningClientTari::run()
|
||||
|
||||
using namespace std::chrono;
|
||||
|
||||
TipInfoResponse prev_tip_info{};
|
||||
auto prev_tip_info_update_time = high_resolution_clock::now();
|
||||
|
||||
auto same_tip = [](const TipInfoResponse& a, const TipInfoResponse& b) -> bool {
|
||||
return
|
||||
(a.metadata().best_block_height() == b.metadata().best_block_height()) &&
|
||||
(a.metadata().best_block_hash() == b.metadata().best_block_hash()) &&
|
||||
(a.metadata().accumulated_difficulty() == b.metadata().accumulated_difficulty()) &&
|
||||
(a.initial_sync_achieved() == b.initial_sync_achieved()) &&
|
||||
(a.base_node_state() == b.base_node_state()) &&
|
||||
(a.failed_checkpoints() == b.failed_checkpoints());
|
||||
};
|
||||
|
||||
for (;;) {
|
||||
const auto t1 = high_resolution_clock::now();
|
||||
const auto start_time = high_resolution_clock::now();
|
||||
|
||||
// Force frequent enough updates (at least every 30 seconds)
|
||||
if (duration_cast<seconds>(start_time - prev_tip_info_update_time).count() >= 30) {
|
||||
prev_tip_info.mutable_metadata()->set_best_block_height(0);
|
||||
}
|
||||
|
||||
MutexLock lock(m_workerLock);
|
||||
|
||||
GetNewBlockTemplateWithCoinbasesRequest request;
|
||||
PowAlgo* algo = new PowAlgo();
|
||||
algo->set_pow_algo(PowAlgo_PowAlgos_POW_ALGOS_RANDOMX);
|
||||
request.clear_algo();
|
||||
request.set_allocated_algo(algo);
|
||||
request.set_max_weight(0);
|
||||
grpc::ClientContext get_tip_info_ctx{};
|
||||
Empty get_tip_info_request{};
|
||||
TipInfoResponse cur_tip_info{};
|
||||
|
||||
NewBlockCoinbase* coinbase = request.add_coinbases();
|
||||
coinbase->set_address(m_auxWallet);
|
||||
const grpc::Status get_tip_info_status = m_TariNode->GetTipInfo(&get_tip_info_ctx, get_tip_info_request, &cur_tip_info);
|
||||
|
||||
// TODO this should be equal to the total weight of shares in the PPLNS window for each wallet
|
||||
coinbase->set_value(1);
|
||||
|
||||
coinbase->set_stealth_payment(false);
|
||||
coinbase->set_revealed_value_proof(true);
|
||||
coinbase->clear_coinbase_extra();
|
||||
|
||||
grpc::ClientContext ctx;
|
||||
GetNewBlockResult response;
|
||||
|
||||
const grpc::Status status = m_TariNode->GetNewBlockTemplateWithCoinbases(&ctx, request, &response);
|
||||
|
||||
if (!status.ok()) {
|
||||
LOGWARN(5, "GetNewBlockTemplateWithCoinbases failed: " << status.error_message());
|
||||
if (!status.error_details().empty()) {
|
||||
LOGWARN(5, "GetNewBlockTemplateWithCoinbases failed: " << status.error_details());
|
||||
if (!get_tip_info_status.ok()) {
|
||||
LOGWARN(4, "GetTipInfo failed: " << get_tip_info_status.error_message());
|
||||
if (!get_tip_info_status.error_details().empty()) {
|
||||
LOGWARN(4, "GetTipInfo failed: " << get_tip_info_status.error_details());
|
||||
}
|
||||
}
|
||||
else {
|
||||
const std::string& id = response.tari_unique_id();
|
||||
const std::string& mm_hash = response.merge_mining_hash();
|
||||
else if (!same_tip(cur_tip_info, prev_tip_info)) {
|
||||
GetNewBlockTemplateWithCoinbasesRequest request{};
|
||||
|
||||
bool ok = true;
|
||||
PowAlgo* algo = new PowAlgo();
|
||||
algo->set_pow_algo(PowAlgo_PowAlgos_POW_ALGOS_RANDOMXM);
|
||||
|
||||
if (id.size() != HASH_SIZE) {
|
||||
LOGERR(1, "Tari unique_id has invalid size (" << id.size() << ')');
|
||||
ok = false;
|
||||
request.clear_algo();
|
||||
request.set_allocated_algo(algo);
|
||||
request.set_max_weight(0);
|
||||
|
||||
NewBlockCoinbase* coinbase = request.add_coinbases();
|
||||
coinbase->set_address(m_auxWallet);
|
||||
|
||||
// TODO this should be equal to the total weight of shares in the PPLNS window for each wallet
|
||||
coinbase->set_value(1);
|
||||
|
||||
coinbase->set_stealth_payment(false);
|
||||
coinbase->set_revealed_value_proof(true);
|
||||
coinbase->clear_coinbase_extra();
|
||||
|
||||
grpc::ClientContext ctx{};
|
||||
GetNewBlockResult response{};
|
||||
|
||||
const grpc::Status status = m_TariNode->GetNewBlockTemplateWithCoinbases(&ctx, request, &response);
|
||||
|
||||
if (!status.ok()) {
|
||||
LOGWARN(4, "GetNewBlockTemplateWithCoinbases failed: " << status.error_message());
|
||||
if (!status.error_details().empty()) {
|
||||
LOGWARN(4, "GetNewBlockTemplateWithCoinbases failed: " << status.error_details());
|
||||
}
|
||||
}
|
||||
else {
|
||||
prev_tip_info = cur_tip_info;
|
||||
prev_tip_info_update_time = start_time;
|
||||
|
||||
if (mm_hash.size() != HASH_SIZE) {
|
||||
LOGERR(1, "Tari merge mining hash has invalid size (" << mm_hash.size() << ')');
|
||||
ok = false;
|
||||
}
|
||||
const std::string& id = response.tari_unique_id();
|
||||
const std::string& mm_hash = response.merge_mining_hash();
|
||||
|
||||
if (ok) {
|
||||
TariJobParams job_params;
|
||||
bool ok = true;
|
||||
|
||||
job_params.height = response.block().header().height();
|
||||
job_params.diff = response.miner_data().target_difficulty();
|
||||
job_params.reward = response.miner_data().reward();
|
||||
job_params.fees = response.miner_data().total_fees();
|
||||
if (id.size() != HASH_SIZE) {
|
||||
LOGERR(1, "Tari unique_id has invalid size (" << id.size() << ')');
|
||||
ok = false;
|
||||
}
|
||||
|
||||
hash chain_id;
|
||||
{
|
||||
WriteLock lock2(m_chainParamsLock);
|
||||
if (mm_hash.size() != HASH_SIZE) {
|
||||
LOGERR(1, "Tari merge mining hash has invalid size (" << mm_hash.size() << ')');
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (job_params != m_tariJobParams) {
|
||||
m_tariJobParams = job_params;
|
||||
if (ok) {
|
||||
TariJobParams job_params;
|
||||
|
||||
if (m_chainParams.aux_id.empty()) {
|
||||
LOGINFO(1, m_hostStr << " uses chain_id " << log::LightCyan() << log::hex_buf(id.data(), id.size()));
|
||||
std::copy(id.begin(), id.end(), m_chainParams.aux_id.h);
|
||||
job_params.height = response.block().header().height();
|
||||
job_params.diff = response.miner_data().target_difficulty();
|
||||
job_params.reward = response.miner_data().reward();
|
||||
job_params.fees = response.miner_data().total_fees();
|
||||
|
||||
hash chain_id;
|
||||
do {
|
||||
WriteLock lock2(m_chainParamsLock);
|
||||
|
||||
if (job_params != m_tariJobParams) {
|
||||
m_tariJobParams = job_params;
|
||||
|
||||
if (m_chainParams.aux_id.empty()) {
|
||||
LOGINFO(1, m_hostStr << " uses chain_id " << log::LightCyan() << log::hex_buf(id.data(), id.size()));
|
||||
std::copy(id.begin(), id.end(), m_chainParams.aux_id.h);
|
||||
}
|
||||
|
||||
chain_id = m_chainParams.aux_id;
|
||||
|
||||
m_previousAuxHashes[(m_previousAuxHashesIndex++) % NUM_PREVIOUS_HASHES] = *m_chainParams.aux_hash.u64();
|
||||
|
||||
std::copy(mm_hash.begin(), mm_hash.end(), m_chainParams.aux_hash.h);
|
||||
|
||||
m_chainParams.aux_diff = static_cast<difficulty_type>(response.miner_data().target_difficulty());
|
||||
|
||||
m_tariBlock = response.block();
|
||||
|
||||
LOGINFO(4, "Tari aux block template: height = " << job_params.height
|
||||
<< ", diff = " << job_params.diff
|
||||
<< ", reward = " << job_params.reward
|
||||
<< ", fees = " << job_params.fees
|
||||
<< ", hash = " << log::hex_buf(mm_hash.data(), mm_hash.size())
|
||||
);
|
||||
}
|
||||
} while (0);
|
||||
|
||||
chain_id = m_chainParams.aux_id;
|
||||
|
||||
std::copy(mm_hash.begin(), mm_hash.end(), m_chainParams.aux_hash.h);
|
||||
m_chainParams.aux_diff = static_cast<difficulty_type>(response.miner_data().target_difficulty());
|
||||
|
||||
m_tariBlock = response.block();
|
||||
|
||||
LOGINFO(5, "Tari block template: height = " << job_params.height
|
||||
<< ", diff = " << job_params.diff
|
||||
<< ", reward = " << job_params.reward
|
||||
<< ", fees = " << job_params.fees
|
||||
<< ", hash = " << log::hex_buf(mm_hash.data(), mm_hash.size())
|
||||
);
|
||||
if (!chain_id.empty()) {
|
||||
m_pool->update_aux_data(chain_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (!chain_id.empty()) {
|
||||
m_pool->update_aux_data(chain_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const int64_t timeout = std::max<int64_t>(500'000'000 - duration_cast<nanoseconds>(high_resolution_clock::now() - t1).count(), 1'000'000);
|
||||
auto dt = duration_cast<nanoseconds>(high_resolution_clock::now() - start_time).count();
|
||||
|
||||
LOGINFO(6, "Polling loop took " << (static_cast<double>(dt) * 1e-6) << " ms");
|
||||
|
||||
const int64_t timeout = std::max<int64_t>(500'000'000 - dt, 1'000'000);
|
||||
|
||||
if ((m_workerStop.load() != 0) || (uv_cond_timedwait(&m_workerCond, &m_workerLock, timeout) != UV_ETIMEDOUT)) {
|
||||
return;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
namespace p2pool {
|
||||
|
||||
class p2pool;
|
||||
struct PoolBlock;
|
||||
|
||||
class MergeMiningClientTari : public IMergeMiningClient, public nocopy_nomove
|
||||
{
|
||||
@@ -33,13 +34,22 @@ public:
|
||||
static constexpr char TARI_PREFIX[] = "tari://";
|
||||
|
||||
bool get_params(ChainParameters& out_params) const override;
|
||||
void submit_solution(const BlockTemplate* block_tpl, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path) override;
|
||||
void on_external_block(const PoolBlock& block) override;
|
||||
void submit_solution(const std::vector<uint8_t>& coinbase_merkle_proof, const uint8_t (&hashing_blob)[128], size_t nonce_offset, const hash& seed_hash, const std::vector<uint8_t>& blob, const std::vector<hash>& merkle_proof, uint32_t merkle_proof_path) override;
|
||||
|
||||
void print_status() const override;
|
||||
|
||||
private:
|
||||
mutable uv_rwlock_t m_chainParamsLock;
|
||||
ChainParameters m_chainParams;
|
||||
|
||||
enum {
|
||||
NUM_PREVIOUS_HASHES = 8,
|
||||
};
|
||||
|
||||
uint64_t m_previousAuxHashes[NUM_PREVIOUS_HASHES];
|
||||
uint32_t m_previousAuxHashesIndex;
|
||||
|
||||
tari::rpc::Block m_tariBlock;
|
||||
|
||||
std::string m_auxWallet;
|
||||
|
||||
+310
-2
@@ -29,6 +29,16 @@
|
||||
#include "p2pool_api.h"
|
||||
#include "stratum_server.h"
|
||||
#include "rapidjson_wrapper.h"
|
||||
#include "merge_mining_client.h"
|
||||
#include "sha256.h"
|
||||
|
||||
#ifdef WITH_TLS
|
||||
#include <openssl/curve25519.h>
|
||||
#else
|
||||
#define ED25519_PUBLIC_KEY_LEN 32
|
||||
#define ED25519_SIGNATURE_LEN 64
|
||||
#endif
|
||||
|
||||
#include <fstream>
|
||||
#include <numeric>
|
||||
|
||||
@@ -37,6 +47,7 @@ LOG_CATEGORY(P2PServer)
|
||||
static constexpr char saved_peer_list_file_name[] = "p2pool_peers.txt";
|
||||
static const char* seed_nodes[] = { "seeds.p2pool.io", "main.p2poolpeers.net", "main.gupax.io", "" };
|
||||
static const char* seed_nodes_mini[] = { "seeds-mini.p2pool.io", "mini.p2poolpeers.net", "mini.gupax.io", "" };
|
||||
static const char* seed_nodes_nano[] = { "seeds-nano.p2pool.io", "nano.p2poolpeers.net", "nano.gupax.io", ""};
|
||||
|
||||
static constexpr int DEFAULT_BACKLOG = 16;
|
||||
static constexpr uint64_t DEFAULT_BAN_TIME = 600;
|
||||
@@ -62,10 +73,13 @@ P2PServer::P2PServer(p2pool* pool)
|
||||
, m_lookForMissingBlocks(true)
|
||||
, m_fastestPeer(nullptr)
|
||||
, m_newP2PoolVersionDetected(false)
|
||||
, m_auxJobLastMessageTimestamp(0)
|
||||
{
|
||||
m_callbackBuf.resize(P2P_BUF_SIZE);
|
||||
m_blockDeserializeBuf.reserve(MAX_BLOCK_SIZE);
|
||||
|
||||
m_auxJobMessages.reserve(1024);
|
||||
|
||||
// Diffuse the initial state in case it has low quality
|
||||
m_rng.discard(10000);
|
||||
|
||||
@@ -105,6 +119,17 @@ P2PServer::P2PServer(p2pool* pool)
|
||||
}
|
||||
m_showPeersAsync.data = this;
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
uv_mutex_init_checked(&m_AuxJobBroadcastLock);
|
||||
|
||||
err = uv_async_init(&m_loop, &m_AuxJobBroadcastAsync, on_aux_job_broadcast);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_async_init failed, error " << uv_err_name(err));
|
||||
PANIC_STOP();
|
||||
}
|
||||
m_AuxJobBroadcastAsync.data = this;
|
||||
#endif
|
||||
|
||||
err = uv_timer_init(&m_loop, &m_timer);
|
||||
if (err) {
|
||||
LOGERR(1, "failed to create timer, error " << uv_err_name(err));
|
||||
@@ -142,6 +167,10 @@ P2PServer::~P2PServer()
|
||||
uv_mutex_destroy(&m_connectToPeersLock);
|
||||
uv_mutex_destroy(&m_showPeersLock);
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
uv_mutex_destroy(&m_AuxJobBroadcastLock);
|
||||
#endif
|
||||
|
||||
delete m_block;
|
||||
delete m_cache;
|
||||
|
||||
@@ -578,6 +607,9 @@ void P2PServer::load_peer_list()
|
||||
else if (m_pool->side_chain().is_mini()) {
|
||||
load_from_seed_nodes(seed_nodes_mini, DEFAULT_P2P_PORT_MINI);
|
||||
}
|
||||
else if (m_pool->side_chain().is_nano()) {
|
||||
load_from_seed_nodes(seed_nodes_nano, DEFAULT_P2P_PORT_NANO);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally load peers from p2pool_peers.txt
|
||||
@@ -670,7 +702,7 @@ void P2PServer::load_monerod_peer_list()
|
||||
|
||||
#undef ERR_STR
|
||||
|
||||
const int port = m_pool->side_chain().is_mini() ? DEFAULT_P2P_PORT_MINI : DEFAULT_P2P_PORT;
|
||||
const int port = m_pool->side_chain().is_mini() ? DEFAULT_P2P_PORT_MINI : (m_pool->side_chain().is_nano() ? DEFAULT_P2P_PORT_NANO : DEFAULT_P2P_PORT);
|
||||
|
||||
const SizeType n = white_list.Size();
|
||||
|
||||
@@ -1008,7 +1040,7 @@ void P2PServer::on_broadcast()
|
||||
return p - buf;
|
||||
});
|
||||
if (!result) {
|
||||
LOGWARN(5, "failed to broadcast to " << static_cast<char*>(client->m_addrString) << ", disconnecting");
|
||||
LOGWARN(5, "failed to broadcast a block to " << static_cast<char*>(client->m_addrString) << ", disconnecting");
|
||||
client->close();
|
||||
break;
|
||||
}
|
||||
@@ -1061,6 +1093,15 @@ void P2PServer::show_peers() const
|
||||
if (client->m_SoftwareVersion) {
|
||||
log::Stream s(buf);
|
||||
s << P2PClient::SoftwareDisplayName(client->m_SoftwareID, client->m_SoftwareVersion);
|
||||
|
||||
// Show protocol version in peer list
|
||||
switch (client->m_protocolVersion) {
|
||||
case PROTOCOL_VERSION_1_0: s << " p1.0"; break;
|
||||
case PROTOCOL_VERSION_1_1: s << " p1.1"; break;
|
||||
case PROTOCOL_VERSION_1_2: s << " p1.2"; break;
|
||||
case PROTOCOL_VERSION_1_3: s << " p1.3"; break;
|
||||
default: s << " p?"; break;
|
||||
}
|
||||
}
|
||||
LOGINFO(0, (client->m_isIncoming ? "I\t" : "O\t")
|
||||
<< log::pad_right(log::Duration(cur_time - client->m_connectedTime), 16) << '\t'
|
||||
@@ -1132,6 +1173,7 @@ void P2PServer::on_timer()
|
||||
check_block_template();
|
||||
check_for_updates();
|
||||
api_update_local_stats();
|
||||
clean_aux_job_messages();
|
||||
}
|
||||
|
||||
void P2PServer::flush_cache()
|
||||
@@ -1374,6 +1416,13 @@ void P2PServer::on_shutdown()
|
||||
MutexLock lock(m_showPeersLock);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_showPeersAsync), nullptr);
|
||||
}
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
{
|
||||
MutexLock lock(m_AuxJobBroadcastLock);
|
||||
uv_close(reinterpret_cast<uv_handle_t*>(&m_AuxJobBroadcastAsync), nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void P2PServer::api_update_local_stats()
|
||||
@@ -1429,6 +1478,112 @@ void P2PServer::api_update_local_stats()
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
void P2PServer::broadcast_aux_job_donation_async(const uint8_t* data, uint32_t data_size, uint64_t timestamp)
|
||||
{
|
||||
MutexLock lock(m_AuxJobBroadcastLock);
|
||||
|
||||
m_AuxJobBroadcast.job.assign(data, data + data_size);
|
||||
m_AuxJobBroadcast.timestamp = timestamp;
|
||||
|
||||
const int err = uv_async_send(&m_AuxJobBroadcastAsync);
|
||||
if (err) {
|
||||
LOGERR(1, "uv_async_send failed, error " << uv_err_name(err));
|
||||
}
|
||||
}
|
||||
|
||||
void P2PServer::broadcast_aux_job_donation_handler()
|
||||
{
|
||||
AuxJobBroadcast auxJobBroadcast;
|
||||
{
|
||||
MutexLock lock(m_AuxJobBroadcastLock);
|
||||
auxJobBroadcast = std::move(m_AuxJobBroadcast);
|
||||
}
|
||||
|
||||
if (auxJobBroadcast.job.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
broadcast_aux_job_donation(auxJobBroadcast.job.data(), static_cast<uint32_t>(auxJobBroadcast.job.size()), auxJobBroadcast.timestamp, nullptr, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
void P2PServer::broadcast_aux_job_donation(const uint8_t* data, uint32_t data_size, uint64_t timestamp, const P2PClient* source, bool duplicate_check_done)
|
||||
{
|
||||
check_event_loop_thread(__func__);
|
||||
|
||||
if (!duplicate_check_done) {
|
||||
hash digest;
|
||||
sha256(data, data_size, digest.h);
|
||||
|
||||
// Every message can be received from multiple peers, so broadcast it only once
|
||||
if (!m_auxJobMessages.emplace(*digest.u64(), timestamp).second) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
m_auxJobLastMessage.assign(data, data + data_size);
|
||||
m_auxJobLastMessageTimestamp = timestamp;
|
||||
|
||||
for (P2PClient* client = static_cast<P2PClient*>(m_connectedClientsList->m_next); client != m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
|
||||
if ((source && (client == source)) || !client->is_good() || (client->m_protocolVersion < PROTOCOL_VERSION_1_3)) {
|
||||
continue;
|
||||
}
|
||||
send_aux_job_donation(client, data, data_size);
|
||||
}
|
||||
}
|
||||
|
||||
void P2PServer::send_aux_job_donation(P2PServer::P2PClient* client, const uint8_t* data, uint32_t data_size)
|
||||
{
|
||||
const bool result = send(client, [client, data, data_size](uint8_t* buf, size_t buf_size) -> size_t {
|
||||
LOGINFO(6, "sending AUX_JOB_DONATION to " << static_cast<char*>(client->m_addrString));
|
||||
|
||||
if (buf_size < 1 + sizeof(uint32_t) + data_size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t* p = buf;
|
||||
|
||||
*(p++) = static_cast<uint8_t>(MessageId::AUX_JOB_DONATION);
|
||||
|
||||
memcpy(p, &data_size, sizeof(uint32_t));
|
||||
p += sizeof(uint32_t);
|
||||
|
||||
memcpy(p, data, data_size);
|
||||
p += data_size;
|
||||
|
||||
return p - buf;
|
||||
});
|
||||
|
||||
if (!result) {
|
||||
LOGWARN(5, "failed to send AUX_JOB_DONATION to " << static_cast<char*>(client->m_addrString) << ", disconnecting");
|
||||
client->close();
|
||||
}
|
||||
}
|
||||
|
||||
void P2PServer::clean_aux_job_messages()
|
||||
{
|
||||
if ((m_timerCounter & 255) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_auxJobMessages.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint64_t cur_time = time(nullptr);
|
||||
|
||||
for (auto it = m_auxJobMessages.begin(); it != m_auxJobMessages.end();) {
|
||||
// Delete old messages only after 3x the timeout to give some leeway for system clock adjustments
|
||||
if (cur_time > it->second + AUX_JOB_TIMEOUT * 3) {
|
||||
it = m_auxJobMessages.erase(it);
|
||||
}
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
P2PServer::P2PClient::~P2PClient()
|
||||
{
|
||||
}
|
||||
@@ -1725,6 +1880,23 @@ bool P2PServer::P2PClient::on_read(const char* data, uint32_t size)
|
||||
on_block_notify(buf + 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case MessageId::AUX_JOB_DONATION:
|
||||
LOGINFO(6, "peer " << log::Gray() << static_cast<char*>(m_addrString) << log::NoColor() << " sent AUX_JOB_DONATION");
|
||||
|
||||
if (bytes_left >= 1 + sizeof(uint32_t)) {
|
||||
const uint32_t msg_size = read_unaligned(reinterpret_cast<uint32_t*>(buf + 1));
|
||||
if (bytes_left >= 1 + sizeof(uint32_t) + msg_size) {
|
||||
bytes_read = 1 + sizeof(uint32_t) + msg_size;
|
||||
|
||||
if (!on_aux_job_donation(buf + 1 + sizeof(uint32_t), msg_size)) {
|
||||
ban(DEFAULT_BAN_TIME);
|
||||
server->remove_peer_from_list(this);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (bytes_read) {
|
||||
@@ -2432,6 +2604,13 @@ void P2PServer::P2PClient::on_peer_list_response(const uint8_t* buf)
|
||||
<< "runs an unknown software with id = " << log::Hex(id_value)
|
||||
);
|
||||
}
|
||||
|
||||
// We know this peer's protocol version now. Send protocol-specific messages here.
|
||||
if ((m_protocolVersion >= PROTOCOL_VERSION_1_3) && !server->m_auxJobLastMessage.empty()) {
|
||||
if (static_cast<uint64_t>(time(nullptr)) < server->m_auxJobLastMessageTimestamp + AUX_JOB_TIMEOUT) {
|
||||
server->send_aux_job_donation(this, server->m_auxJobLastMessage.data(), static_cast<uint32_t>(server->m_auxJobLastMessage.size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -2510,6 +2689,135 @@ void P2PServer::P2PClient::on_block_notify(const uint8_t* buf)
|
||||
}
|
||||
}
|
||||
|
||||
bool P2PServer::P2PClient::on_aux_job_donation(const uint8_t* buf, uint32_t size)
|
||||
{
|
||||
P2PServer* server = static_cast<P2PServer*>(m_owner);
|
||||
|
||||
// Ignore the same message coming from other peers
|
||||
if ((server->m_auxJobLastMessage.size() == size) && (memcmp(server->m_auxJobLastMessage.data(), buf, size) == 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const time_t cur_time = time(nullptr);
|
||||
|
||||
// Layout of the message:
|
||||
//
|
||||
// 32 bytes | Secondary public key
|
||||
// 8 bytes | Secondary public key's expiration timestamp
|
||||
// 64 bytes | Master key signature signing the above 40 bytes
|
||||
// (size - 168) bytes | Data
|
||||
// 64 bytes | Secondary key signature signing the data
|
||||
|
||||
constexpr uint32_t DATA_OFFSET = ED25519_PUBLIC_KEY_LEN + 8 + ED25519_SIGNATURE_LEN;
|
||||
constexpr uint32_t OVERHEAD = DATA_OFFSET + ED25519_SIGNATURE_LEN;
|
||||
constexpr uint32_t DATA_ENTRY_SIZE = HASH_SIZE * 2 + sizeof(difficulty_type);
|
||||
constexpr uint32_t MIN_DATA_SIZE = sizeof(uint64_t) + DATA_ENTRY_SIZE;
|
||||
|
||||
// Ignore invalid or empty messages
|
||||
if (size < OVERHEAD + MIN_DATA_SIZE) {
|
||||
LOGWARN(4, "peer " << static_cast<char*>(m_addrString) << " sent an invalid AUX_JOB_DONATION message (" << size << " < " << (OVERHEAD + MIN_DATA_SIZE) << ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Layout of the data:
|
||||
//
|
||||
// 8 bytes | timestamp
|
||||
//
|
||||
// Next come one or multiple data entries:
|
||||
//
|
||||
// 32 bytes | aux_id
|
||||
// 32 bytes | aux_hash
|
||||
// 16 bytes | aux_diff
|
||||
|
||||
const uint32_t data_size = size - OVERHEAD;
|
||||
|
||||
const int64_t secondary_key_expiration_time = read_unaligned(reinterpret_cast<const int64_t*>(buf + ED25519_PUBLIC_KEY_LEN));
|
||||
|
||||
// Ignore messages signed with an outdated secondary key
|
||||
if (cur_time >= secondary_key_expiration_time) {
|
||||
LOGWARN(4, "peer " << static_cast<char*>(m_addrString) << " sent an AUX_JOB_DONATION message with an expired secondary key (" << cur_time << " >= " << secondary_key_expiration_time << ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check secondary public key's signature
|
||||
uint8_t signature[ED25519_SIGNATURE_LEN];
|
||||
memcpy(signature, buf + ED25519_PUBLIC_KEY_LEN + 8, sizeof(signature));
|
||||
|
||||
// Ignore messages with invalid signatures
|
||||
#ifdef WITH_TLS // Need BoringSSL to verify signatures
|
||||
if (!ED25519_verify(buf, ED25519_PUBLIC_KEY_LEN + 8, signature, ED25519_MASTER_PUBLIC_KEY)) {
|
||||
LOGWARN(4, "peer " << static_cast<char*>(m_addrString) << " sent an AUX_JOB_DONATION message with an invalid master key signature");
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
const uint8_t* p = buf + DATA_OFFSET;
|
||||
const uint8_t* data_end = p + data_size;
|
||||
|
||||
memcpy(signature, data_end, sizeof(signature));
|
||||
|
||||
uint8_t secondary_public_key[ED25519_PUBLIC_KEY_LEN];
|
||||
memcpy(secondary_public_key, buf, sizeof(secondary_public_key));
|
||||
|
||||
// Ignore messages with invalid signatures
|
||||
#ifdef WITH_TLS // Need BoringSSL to verify signatures
|
||||
if (!ED25519_verify(p, data_size, signature, secondary_public_key)) {
|
||||
LOGWARN(4, "peer " << static_cast<char*>(m_addrString) << " sent an AUX_JOB_DONATION message with an invalid secondary key signature");
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
const int64_t data_timestamp = read_unaligned(reinterpret_cast<const int64_t*>(p));
|
||||
p += sizeof(int64_t);
|
||||
|
||||
// Ignore outdated messages
|
||||
if (cur_time >= data_timestamp + AUX_JOB_TIMEOUT) {
|
||||
LOGWARN(4, "peer " << static_cast<char*>(m_addrString) << " sent an outdated AUX_JOB_DONATION message (" << cur_time << " >= " << data_timestamp << " + " << static_cast<int>(AUX_JOB_TIMEOUT) << ')');
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((data_end - p) % DATA_ENTRY_SIZE) {
|
||||
LOGWARN(4, "peer " << static_cast<char*>(m_addrString) << " sent an invalid AUX_JOB_DONATION message (" << (data_end - p) << " is not a multiple of " << DATA_ENTRY_SIZE << ')');
|
||||
return true;
|
||||
}
|
||||
|
||||
hash digest;
|
||||
sha256(buf, size, digest.h);
|
||||
|
||||
// Ignore repeated old messages
|
||||
if (!server->m_auxJobMessages.emplace(*digest.u64(), data_timestamp).second) {
|
||||
LOGWARN(5, "peer " << static_cast<char*>(m_addrString) << " sent an old AUX_JOB_DONATION message (" << (cur_time - data_timestamp) << " seconds old)");
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(WITH_MERGE_MINING_DONATION) && defined(WITH_TLS) // Only work on verified jobs
|
||||
const uint32_t N = static_cast<uint32_t>(data_end - p) / DATA_ENTRY_SIZE;
|
||||
|
||||
std::vector<IMergeMiningClient::ChainParameters> chain_params_vec(N);
|
||||
|
||||
for (uint32_t i = 0; i < N; ++i) {
|
||||
IMergeMiningClient::ChainParameters& chain_params = chain_params_vec[i];
|
||||
|
||||
memcpy(chain_params.aux_id.h, p, HASH_SIZE);
|
||||
p += HASH_SIZE;
|
||||
|
||||
memcpy(chain_params.aux_hash.h, p, HASH_SIZE);
|
||||
p += HASH_SIZE;
|
||||
|
||||
chain_params.aux_diff.lo = read_unaligned(reinterpret_cast<const uint64_t*>(p));
|
||||
p += sizeof(uint64_t);
|
||||
|
||||
chain_params.aux_diff.hi = read_unaligned(reinterpret_cast<const uint64_t*>(p));
|
||||
p += sizeof(uint64_t);
|
||||
}
|
||||
|
||||
server->m_pool->set_aux_job_donation(chain_params_vec);
|
||||
#endif
|
||||
|
||||
server->broadcast_aux_job_donation(buf, size, data_timestamp, this, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool P2PServer::P2PClient::handle_incoming_block_async(const PoolBlock* block, uint64_t max_time_delta)
|
||||
{
|
||||
P2PServer* server = static_cast<P2PServer*>(m_owner);
|
||||
|
||||
+41
-2
@@ -34,12 +34,14 @@ static_assert((P2P_BUF_SIZE & (P2P_BUF_SIZE - 1)) == 0, "P2P_BUF_SIZE is not a p
|
||||
static constexpr size_t PEER_LIST_RESPONSE_MAX_PEERS = 16;
|
||||
static constexpr int DEFAULT_P2P_PORT = 37889;
|
||||
static constexpr int DEFAULT_P2P_PORT_MINI = 37888;
|
||||
static constexpr int DEFAULT_P2P_PORT_NANO = 37890;
|
||||
|
||||
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 PROTOCOL_VERSION_1_3 = 0x00010003UL;
|
||||
|
||||
static constexpr uint32_t SUPPORTED_PROTOCOL_VERSION = PROTOCOL_VERSION_1_2;
|
||||
static constexpr uint32_t SUPPORTED_PROTOCOL_VERSION = PROTOCOL_VERSION_1_3;
|
||||
|
||||
class P2PServer : public TCPServer
|
||||
{
|
||||
@@ -55,7 +57,9 @@ public:
|
||||
PEER_LIST_RESPONSE,
|
||||
BLOCK_BROADCAST_COMPACT,
|
||||
BLOCK_NOTIFY,
|
||||
LAST = BLOCK_NOTIFY,
|
||||
// Donation messages are signed by author's private keys to prevent their abuse/misuse.
|
||||
AUX_JOB_DONATION,
|
||||
LAST = AUX_JOB_DONATION,
|
||||
};
|
||||
|
||||
explicit P2PServer(p2pool *pool);
|
||||
@@ -113,6 +117,7 @@ public:
|
||||
[[nodiscard]] 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);
|
||||
[[nodiscard]] bool on_aux_job_donation(const uint8_t* buf, uint32_t size);
|
||||
|
||||
[[nodiscard]] bool handle_incoming_block_async(const PoolBlock* block, uint64_t max_time_delta = 0);
|
||||
static void handle_incoming_block(p2pool* pool, PoolBlock& block, std::vector<hash>& missing_blocks, bool& result);
|
||||
@@ -188,6 +193,12 @@ public:
|
||||
|
||||
bool disconnected() const { return m_seenGoodPeers && (m_numConnections == 0); };
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
void broadcast_aux_job_donation_async(const uint8_t* data, uint32_t data_size, uint64_t timestamp);
|
||||
#endif
|
||||
|
||||
void broadcast_aux_job_donation(const uint8_t* data, uint32_t data_size, uint64_t timestamp, const P2PClient* source, bool duplicate_check_done);
|
||||
|
||||
private:
|
||||
[[nodiscard]] const char* get_log_category() const override;
|
||||
|
||||
@@ -291,6 +302,34 @@ private:
|
||||
void on_shutdown() override;
|
||||
|
||||
void api_update_local_stats();
|
||||
|
||||
enum {
|
||||
AUX_JOB_TIMEOUT = 3600,
|
||||
};
|
||||
|
||||
unordered_set<std::pair<uint64_t, uint64_t>> m_auxJobMessages;
|
||||
std::vector<uint8_t> m_auxJobLastMessage;
|
||||
uint64_t m_auxJobLastMessageTimestamp;
|
||||
|
||||
void send_aux_job_donation(P2PServer::P2PClient* client, const uint8_t* data, uint32_t data_size);
|
||||
|
||||
void clean_aux_job_messages();
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
struct AuxJobBroadcast
|
||||
{
|
||||
std::vector<uint8_t> job;
|
||||
uint64_t timestamp = 0;
|
||||
};
|
||||
|
||||
uv_mutex_t m_AuxJobBroadcastLock;
|
||||
AuxJobBroadcast m_AuxJobBroadcast;
|
||||
|
||||
uv_async_t m_AuxJobBroadcastAsync;
|
||||
|
||||
static void on_aux_job_broadcast(uv_async_t* handle) { reinterpret_cast<P2PServer*>(handle->data)->broadcast_aux_job_donation_handler(); }
|
||||
void broadcast_aux_job_donation_handler();
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace p2pool
|
||||
|
||||
+296
-36
@@ -38,14 +38,17 @@
|
||||
#include "keccak.h"
|
||||
#include "merkle.h"
|
||||
#include "merge_mining_client.h"
|
||||
|
||||
#ifdef WITH_TLS
|
||||
#include <openssl/curve25519.h>
|
||||
#endif
|
||||
|
||||
#include <thread>
|
||||
#include <fstream>
|
||||
#include <numeric>
|
||||
|
||||
LOG_CATEGORY(P2Pool)
|
||||
|
||||
constexpr int BLOCK_HEADERS_REQUIRED = 720;
|
||||
|
||||
constexpr uint64_t SEEDHASH_EPOCH_BLOCKS = 2048;
|
||||
constexpr uint64_t SEEDHASH_EPOCH_LAG = 64;
|
||||
|
||||
@@ -53,6 +56,8 @@ constexpr char FOUND_BLOCKS_FILE[] = "p2pool.blocks";
|
||||
|
||||
namespace p2pool {
|
||||
|
||||
static uint64_t BLOCK_HEADERS_REQUIRED = 720;
|
||||
|
||||
p2pool::p2pool(int argc, char* argv[])
|
||||
: m_stopped(false)
|
||||
, m_updateSeed(true)
|
||||
@@ -73,6 +78,11 @@ p2pool::p2pool(int argc, char* argv[])
|
||||
|
||||
m_params = p;
|
||||
|
||||
// P2Pool-nano requires more Monero blocks for the initial sync
|
||||
if (m_params->m_nano) {
|
||||
BLOCK_HEADERS_REQUIRED = 1440;
|
||||
}
|
||||
|
||||
bkg_jobs_tracker = new BackgroundJobTracker();
|
||||
|
||||
#ifdef WITH_UPNP
|
||||
@@ -148,11 +158,18 @@ p2pool::p2pool(int argc, char* argv[])
|
||||
uv_rwlock_init_checked(&m_minerDataLock);
|
||||
uv_rwlock_init_checked(&m_ZMQReaderLock);
|
||||
uv_rwlock_init_checked(&m_mergeMiningClientsLock);
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
uv_rwlock_init_checked(&m_auxJobDonationLock);
|
||||
#endif
|
||||
|
||||
uv_rwlock_init_checked(&m_auxIdLock);
|
||||
uv_mutex_init_checked(&m_foundBlocksLock);
|
||||
|
||||
#ifdef WITH_RANDOMX
|
||||
uv_mutex_init_checked(&m_minerLock);
|
||||
#endif
|
||||
|
||||
uv_mutex_init_checked(&m_submitBlockDataLock);
|
||||
uv_mutex_init_checked(&m_submitAuxBlockDataLock);
|
||||
|
||||
@@ -163,10 +180,10 @@ p2pool::p2pool(int argc, char* argv[])
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
m_sideChain = new SideChain(this, type, p->m_mini ? "mini" : nullptr);
|
||||
m_sideChain = new SideChain(this, type, p->m_mini ? "mini" : (p->m_nano ? "nano" : nullptr));
|
||||
|
||||
if (p->m_p2pAddresses.empty()) {
|
||||
const int p2p_port = m_sideChain->is_mini() ? DEFAULT_P2P_PORT_MINI : DEFAULT_P2P_PORT;
|
||||
const int p2p_port = m_sideChain->is_mini() ? DEFAULT_P2P_PORT_MINI : (m_sideChain->is_nano() ? DEFAULT_P2P_PORT_NANO : DEFAULT_P2P_PORT);
|
||||
|
||||
char buf[48] = {};
|
||||
log::Stream s(buf);
|
||||
@@ -222,11 +239,18 @@ p2pool::~p2pool()
|
||||
uv_rwlock_destroy(&m_minerDataLock);
|
||||
uv_rwlock_destroy(&m_ZMQReaderLock);
|
||||
uv_rwlock_destroy(&m_mergeMiningClientsLock);
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
uv_rwlock_destroy(&m_auxJobDonationLock);
|
||||
#endif
|
||||
|
||||
uv_rwlock_destroy(&m_auxIdLock);
|
||||
uv_mutex_destroy(&m_foundBlocksLock);
|
||||
|
||||
#ifdef WITH_RANDOMX
|
||||
uv_mutex_destroy(&m_minerLock);
|
||||
#endif
|
||||
|
||||
uv_mutex_destroy(&m_submitBlockDataLock);
|
||||
uv_mutex_destroy(&m_submitAuxBlockDataLock);
|
||||
|
||||
@@ -565,6 +589,27 @@ void p2pool::handle_chain_main(ChainMain& data, const char* extra)
|
||||
m_zmqLastActive = seconds_since_epoch();
|
||||
}
|
||||
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
void p2pool::set_aux_job_donation(const std::vector<IMergeMiningClient::ChainParameters>& chain_params)
|
||||
{
|
||||
if (m_stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint64_t t = seconds_since_epoch();
|
||||
{
|
||||
WriteLock lock(m_auxJobDonationLock);
|
||||
m_auxJobDonation = chain_params;
|
||||
m_auxJobDonationLastUpdated = t;
|
||||
}
|
||||
|
||||
if (!chain_params.empty()) {
|
||||
update_aux_data(chain_params.front().aux_id);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void p2pool::update_aux_data(const hash& chain_id)
|
||||
{
|
||||
if (m_stopped) {
|
||||
@@ -574,6 +619,22 @@ void p2pool::update_aux_data(const hash& chain_id)
|
||||
MinerData data;
|
||||
std::vector<hash> aux_id;
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
std::vector<IMergeMiningClient::ChainParameters> mm_donation_params;
|
||||
uint64_t mm_donation_params_last_updated;
|
||||
{
|
||||
ReadLock lock(m_auxJobDonationLock);
|
||||
mm_donation_params = m_auxJobDonation;
|
||||
mm_donation_params_last_updated = m_auxJobDonationLastUpdated;
|
||||
}
|
||||
|
||||
const uint64_t t = seconds_since_epoch();
|
||||
|
||||
if (!mm_donation_params.empty()) {
|
||||
LOGINFO(5, "update_aux_data: there are " << mm_donation_params.size() << " aux chain datas for merge mining donation, last updated " << (t - mm_donation_params_last_updated) << " seconds ago");
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
ReadLock lock(m_mergeMiningClientsLock);
|
||||
|
||||
@@ -588,13 +649,33 @@ void p2pool::update_aux_data(const hash& chain_id)
|
||||
if (c->get_params(chain_params)) {
|
||||
data.aux_chains.emplace_back(chain_params.aux_id, chain_params.aux_hash, chain_params.aux_diff);
|
||||
aux_id.emplace_back(chain_params.aux_id);
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
// If the user is already merge mining this chain, don't use it for donation
|
||||
mm_donation_params.erase(std::remove_if(mm_donation_params.begin(), mm_donation_params.end(), [&chain_params](const auto& t) { return t.aux_id == chain_params.aux_id; }), mm_donation_params.end());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
aux_id.emplace_back(m_sideChain->consensus_hash());
|
||||
}
|
||||
}
|
||||
|
||||
if (!aux_id.empty()) {
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
// Use the donation job for 30 minutes at most if it doesn't get updated anymore
|
||||
if (t <= mm_donation_params_last_updated + 1800) {
|
||||
LOGINFO(5, "update_aux_data: using " << mm_donation_params.size() << " aux chain datas for merge mining donation");
|
||||
|
||||
for (const IMergeMiningClient::ChainParameters& c : mm_donation_params) {
|
||||
data.aux_chains.emplace_back(c.aux_id, c.aux_hash, c.aux_diff);
|
||||
aux_id.emplace_back(c.aux_id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOGINFO(5, "update_aux_data: merge mining donation data is stale, not using it");
|
||||
}
|
||||
#endif
|
||||
|
||||
aux_id.emplace_back(m_sideChain->consensus_hash());
|
||||
{
|
||||
WriteLock lock(m_auxIdLock);
|
||||
|
||||
if (aux_id == m_auxId) {
|
||||
@@ -605,7 +686,7 @@ void p2pool::update_aux_data(const hash& chain_id)
|
||||
m_auxNonce = data.aux_nonce;
|
||||
}
|
||||
else {
|
||||
LOGERR(1, "Failed to find the aux nonce for merge mining. Merge mining will be off this round.");
|
||||
LOGERR(1, "update_aux_data: failed to find the aux nonce for merge mining. Merge mining will be off this round.");
|
||||
data.aux_chains.clear();
|
||||
}
|
||||
}
|
||||
@@ -623,16 +704,111 @@ void p2pool::update_aux_data(const hash& chain_id)
|
||||
}
|
||||
|
||||
if (!chain_id.empty()) {
|
||||
LOGINFO(4, "New aux data from chain " << chain_id);
|
||||
LOGINFO(4, "update_aux_data: new aux data from chain " << chain_id);
|
||||
|
||||
if (!is_main_thread()) {
|
||||
update_block_template_async();
|
||||
}
|
||||
else {
|
||||
update_block_template();
|
||||
}
|
||||
|
||||
#if defined(WITH_MERGE_MINING_DONATION) && defined(WITH_TLS)
|
||||
send_aux_job_donation();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
void p2pool::send_aux_job_donation()
|
||||
{
|
||||
#ifdef WITH_TLS
|
||||
if (m_params->m_authorKeyFile.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::ifstream f(m_params->m_authorKeyFile, std::ios::binary | std::ios::ate);
|
||||
|
||||
if (!f.good()) {
|
||||
LOGERR(1, "send_aux_job_donation: failed to open " << m_params->m_authorKeyFile);
|
||||
return;
|
||||
}
|
||||
|
||||
Params::AuthorKey key;
|
||||
|
||||
if (f.tellg() != static_cast<std::streampos>(sizeof(key))) {
|
||||
LOGERR(1, "send_aux_job_donation: " << m_params->m_authorKeyFile << " has an invalid size");
|
||||
return;
|
||||
}
|
||||
|
||||
f.seekg(0);
|
||||
f.read(reinterpret_cast<char*>(&key), sizeof(key));
|
||||
|
||||
if (!f.good()) {
|
||||
LOGERR(1, "send_aux_job_donation: failed to read data from " << m_params->m_authorKeyFile);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint64_t timestamp = time(nullptr);
|
||||
|
||||
if (timestamp >= read_unaligned(reinterpret_cast<uint64_t*>(key.expiration_time))) {
|
||||
LOGERR(1, "send_aux_job_donation: " << m_params->m_authorKeyFile << " is expired");
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t* p = reinterpret_cast<uint8_t*>(&key);
|
||||
|
||||
if (!ED25519_verify(p, sizeof(key.pub_key) + sizeof(key.expiration_time), key.master_key_signature, ED25519_MASTER_PUBLIC_KEY)) {
|
||||
LOGERR(1, "send_aux_job_donation: " << m_params->m_authorKeyFile << ": signature verification failed");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> job;
|
||||
job.reserve(512);
|
||||
|
||||
constexpr uint32_t DATA_OFFSET = sizeof(key.pub_key) + sizeof(key.expiration_time) + sizeof(key.master_key_signature);
|
||||
|
||||
job.assign(p, p + DATA_OFFSET);
|
||||
|
||||
job.insert(job.end(), reinterpret_cast<const uint8_t*>(×tamp), reinterpret_cast<const uint8_t*>(×tamp) + sizeof(uint64_t));
|
||||
|
||||
{
|
||||
ReadLock lock(m_minerDataLock);
|
||||
|
||||
if (m_minerData.aux_chains.empty()) {
|
||||
LOGERR(1, "send_aux_job_donation: no merge mined chains found");
|
||||
return;
|
||||
}
|
||||
|
||||
for (const AuxChainData& c : m_minerData.aux_chains) {
|
||||
job.insert(job.end(), c.unique_id.h, c.unique_id.h + HASH_SIZE);
|
||||
job.insert(job.end(), c.data.h, c.data.h + HASH_SIZE);
|
||||
job.insert(job.end(), reinterpret_cast<const uint8_t*>(&c.difficulty), reinterpret_cast<const uint8_t*>(&c.difficulty) + sizeof(difficulty_type));
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t signature[64];
|
||||
if (!ED25519_sign(signature, job.data() + DATA_OFFSET, job.size() - DATA_OFFSET, key.priv_key)) {
|
||||
LOGERR(1, "send_aux_job_donation: failed to sign the donation job");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ED25519_verify(job.data() + DATA_OFFSET, job.size() - DATA_OFFSET, signature, key.pub_key)) {
|
||||
LOGERR(1, "send_aux_job_donation: failed to verify the donation job's signature");
|
||||
return;
|
||||
}
|
||||
|
||||
OPENSSL_cleanse(&key, sizeof(key));
|
||||
|
||||
job.insert(job.end(), signature, signature + sizeof(signature));
|
||||
|
||||
m_p2pServer->broadcast_aux_job_donation_async(job.data(), static_cast<uint32_t>(job.size()), timestamp);
|
||||
#else
|
||||
LOGERR(1, "p2pool::send_aux_job_donation() must be built with TLS");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void p2pool::submit_block_async(uint32_t template_id, uint32_t nonce, uint32_t extra_nonce)
|
||||
{
|
||||
{
|
||||
@@ -769,7 +945,7 @@ void p2pool::submit_aux_block() const
|
||||
}
|
||||
}
|
||||
|
||||
c->submit_solution(block_tpl, hashing_blob, nonce_offset, seed_hash, blob, proof, path);
|
||||
c->submit_solution(block_tpl->get_coinbase_merkle_proof(), hashing_blob, nonce_offset, seed_hash, blob, proof, path);
|
||||
}
|
||||
else {
|
||||
LOGWARN(3, "submit_aux_block: failed to get merkle proof for chain_id " << chain_id);
|
||||
@@ -977,7 +1153,7 @@ void p2pool::update_block_template()
|
||||
#endif
|
||||
}
|
||||
|
||||
void p2pool::download_block_headers(uint64_t current_height)
|
||||
void p2pool::download_block_headers1(uint64_t current_height)
|
||||
{
|
||||
const uint64_t seed_height = get_seed_height(current_height);
|
||||
const uint64_t prev_seed_height = (seed_height > SEEDHASH_EPOCH_BLOCKS) ? (seed_height - SEEDHASH_EPOCH_BLOCKS) : 0;
|
||||
@@ -987,37 +1163,107 @@ void p2pool::download_block_headers(uint64_t current_height)
|
||||
|
||||
const Params::Host& host = current_host();
|
||||
|
||||
// First download 2 RandomX seeds
|
||||
const uint64_t seed_heights[2] = { prev_seed_height, seed_height };
|
||||
for (uint64_t height : seed_heights) {
|
||||
s.m_pos = 0;
|
||||
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_header_by_height\",\"params\":{\"height\":" << prev_seed_height << "}}\0";
|
||||
|
||||
JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
[this, prev_seed_height, current_height](const char* data, size_t size, double) {
|
||||
ChainMain block;
|
||||
if (parse_block_header(data, size, block)) {
|
||||
// Do it synchronously to make sure stratum and p2p don't start before it's finished
|
||||
m_hasher->set_old_seed(block.id);
|
||||
download_block_headers2(current_height);
|
||||
}
|
||||
else {
|
||||
LOGERR(1, "fatal error: couldn't download block header for seed height " << prev_seed_height);
|
||||
download_block_headers1(current_height);
|
||||
}
|
||||
},
|
||||
[this, prev_seed_height, current_height](const char* data, size_t size, double) {
|
||||
if (size > 0) {
|
||||
LOGERR(1, "fatal error: couldn't download block header for seed height " << prev_seed_height << ", error " << log::const_buf(data, size));
|
||||
download_block_headers1(current_height);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void p2pool::download_block_headers2(uint64_t current_height)
|
||||
{
|
||||
const uint64_t seed_height = get_seed_height(current_height);
|
||||
|
||||
char buf[log::Stream::BUF_SIZE + 1] = {};
|
||||
log::Stream s(buf);
|
||||
|
||||
const Params::Host& host = current_host();
|
||||
|
||||
s.m_pos = 0;
|
||||
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_header_by_height\",\"params\":{\"height\":" << seed_height << "}}\0";
|
||||
|
||||
JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
[this, seed_height, current_height](const char* data, size_t size, double) {
|
||||
ChainMain block;
|
||||
if (parse_block_header(data, size, block)) {
|
||||
const uint64_t start_height = (current_height > BLOCK_HEADERS_REQUIRED) ? (current_height - BLOCK_HEADERS_REQUIRED) : 0;
|
||||
download_block_headers3(start_height, current_height);
|
||||
}
|
||||
else {
|
||||
LOGERR(1, "fatal error: couldn't download block header for seed height " << seed_height);
|
||||
download_block_headers2(current_height);
|
||||
}
|
||||
},
|
||||
[this, seed_height, current_height](const char* data, size_t size, double) {
|
||||
if (size > 0) {
|
||||
LOGERR(1, "fatal error: couldn't download block header for seed height " << seed_height << ", error " << log::const_buf(data, size));
|
||||
download_block_headers2(current_height);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void p2pool::download_block_headers3(uint64_t start_height, uint64_t current_height)
|
||||
{
|
||||
// Workaround the restricted RPC limit
|
||||
constexpr uint64_t RESTRICTED_BLOCK_HEADER_RANGE = 1000;
|
||||
|
||||
if (current_height - start_height > RESTRICTED_BLOCK_HEADER_RANGE + 1) {
|
||||
char buf[log::Stream::BUF_SIZE + 1] = {};
|
||||
log::Stream s(buf);
|
||||
|
||||
const Params::Host& host = current_host();
|
||||
|
||||
const uint64_t next_height = start_height + RESTRICTED_BLOCK_HEADER_RANGE;
|
||||
|
||||
s.m_pos = 0;
|
||||
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_header_by_height\",\"params\":{\"height\":" << height << "}}\0";
|
||||
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_headers_range\",\"params\":{\"start_height\":" << start_height << ",\"end_height\":" << next_height << "}}\0";
|
||||
|
||||
JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
[this, prev_seed_height, height](const char* data, size_t size, double)
|
||||
{
|
||||
ChainMain block;
|
||||
if (parse_block_header(data, size, block)) {
|
||||
if (height == prev_seed_height) {
|
||||
// Do it synchronously to make sure stratum and p2p don't start before it's finished
|
||||
m_hasher->set_old_seed(block.id);
|
||||
}
|
||||
[this, start_height, next_height, host, current_height](const char* data, size_t size, double) {
|
||||
if (parse_block_headers_range(data, size) == next_height - start_height + 1) {
|
||||
download_block_headers3(next_height + 1, current_height);
|
||||
}
|
||||
else {
|
||||
LOGERR(1, "fatal error: couldn't download block header for seed height " << height);
|
||||
PANIC_STOP();
|
||||
LOGERR(1, "Couldn't download block headers for heights " << start_height << " - " << next_height);
|
||||
download_block_headers3(start_height, current_height);
|
||||
}
|
||||
},
|
||||
[height](const char* data, size_t size, double)
|
||||
{
|
||||
[this, start_height, next_height, current_height](const char* data, size_t size, double) {
|
||||
if (size > 0) {
|
||||
LOGERR(1, "fatal error: couldn't download block header for seed height " << height << ", error " << log::const_buf(data, size));
|
||||
PANIC_STOP();
|
||||
LOGERR(1, "Couldn't download block headers for heights " << start_height << " - " << next_height << ", error " << log::const_buf(data, size));
|
||||
download_block_headers3(start_height, current_height);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
else {
|
||||
download_block_headers4(start_height, current_height);
|
||||
}
|
||||
}
|
||||
|
||||
const uint64_t start_height = (current_height > BLOCK_HEADERS_REQUIRED) ? (current_height - BLOCK_HEADERS_REQUIRED) : 0;
|
||||
void p2pool::download_block_headers4(uint64_t start_height, uint64_t current_height)
|
||||
{
|
||||
char buf[log::Stream::BUF_SIZE + 1] = {};
|
||||
log::Stream s(buf);
|
||||
|
||||
const Params::Host& host = current_host();
|
||||
|
||||
s.m_pos = 0;
|
||||
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_headers_range\",\"params\":{\"start_height\":" << start_height << ",\"end_height\":" << current_height - 1 << "}}\0";
|
||||
@@ -1080,14 +1326,14 @@ void p2pool::download_block_headers(uint64_t current_height)
|
||||
}
|
||||
else {
|
||||
LOGERR(1, "Couldn't download block headers for heights " << start_height << " - " << current_height - 1);
|
||||
download_block_headers(current_height);
|
||||
download_block_headers4(start_height, current_height);
|
||||
}
|
||||
},
|
||||
[this, start_height, current_height](const char* data, size_t size, double)
|
||||
{
|
||||
if (size > 0) {
|
||||
LOGERR(1, "Couldn't download block headers for heights " << start_height << " - " << current_height - 1 << ", error " << log::const_buf(data, size));
|
||||
download_block_headers(current_height);
|
||||
download_block_headers4(start_height, current_height);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1439,7 +1685,7 @@ void p2pool::parse_get_miner_data_rpc(const char* data, size_t size)
|
||||
|
||||
handle_miner_data(minerData);
|
||||
if (m_serversStarted.load() == 0) {
|
||||
download_block_headers(minerData.height);
|
||||
download_block_headers1(minerData.height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1693,7 +1939,7 @@ void p2pool::cleanup_mainchain_data(uint64_t height)
|
||||
// Expects m_mainchainLock to be already locked here
|
||||
// Deletes everything older than 720 blocks, except for the 3 latest RandomX seed heights
|
||||
|
||||
constexpr uint64_t PRUNE_DISTANCE = BLOCK_HEADERS_REQUIRED;
|
||||
const uint64_t PRUNE_DISTANCE = BLOCK_HEADERS_REQUIRED;
|
||||
const uint64_t seed_height = get_seed_height(height);
|
||||
const std::array<uint64_t, 3> seed_heights{ seed_height, seed_height - SEEDHASH_EPOCH_BLOCKS, seed_height - SEEDHASH_EPOCH_BLOCKS * 2 };
|
||||
|
||||
@@ -1769,6 +2015,15 @@ void p2pool::api_update_block_found(const ChainMain* data, const PoolBlock* bloc
|
||||
}
|
||||
}
|
||||
|
||||
void p2pool::on_external_block(const PoolBlock& block)
|
||||
{
|
||||
ReadLock lock(m_mergeMiningClientsLock);
|
||||
|
||||
for (IMergeMiningClient* c : m_mergeMiningClients) {
|
||||
c->on_external_block(block);
|
||||
}
|
||||
}
|
||||
|
||||
bool p2pool::get_difficulty_at_height(uint64_t height, difficulty_type& diff)
|
||||
{
|
||||
ReadLock lock(m_mainchainLock);
|
||||
@@ -1956,7 +2211,7 @@ int p2pool::run()
|
||||
loop->data = nullptr;
|
||||
GetLoopUserData(loop);
|
||||
|
||||
set_thread_name("Main");
|
||||
set_thread_name("p2pool");
|
||||
|
||||
try {
|
||||
get_info();
|
||||
@@ -1979,7 +2234,12 @@ int p2pool::run()
|
||||
bkg_jobs_tracker->wait();
|
||||
|
||||
#ifdef WITH_RANDOMX
|
||||
delete m_miner;
|
||||
{
|
||||
MutexLock lock(m_minerLock);
|
||||
|
||||
delete m_miner;
|
||||
m_miner = nullptr;
|
||||
}
|
||||
#endif
|
||||
delete m_stratumServer;
|
||||
delete m_p2pServer;
|
||||
|
||||
+18
-1
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "uv_util.h"
|
||||
#include "params.h"
|
||||
#include "merge_mining_client.h"
|
||||
#include <map>
|
||||
|
||||
namespace p2pool {
|
||||
@@ -86,6 +87,11 @@ public:
|
||||
virtual void handle_miner_data(MinerData& data) override;
|
||||
virtual void handle_chain_main(ChainMain& data, const char* extra) override;
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
void set_aux_job_donation(const std::vector<IMergeMiningClient::ChainParameters>& chain_params);
|
||||
void send_aux_job_donation();
|
||||
#endif
|
||||
|
||||
void update_aux_data(const hash& chain_id);
|
||||
|
||||
void submit_block_async(uint32_t template_id, uint32_t nonce, uint32_t extra_nonce);
|
||||
@@ -106,11 +112,16 @@ public:
|
||||
void update_block_template_async(bool is_alternative_block = false);
|
||||
void update_block_template();
|
||||
|
||||
void download_block_headers(uint64_t current_height);
|
||||
// TODO refactor this bullshit later
|
||||
void download_block_headers1(uint64_t current_height);
|
||||
void download_block_headers2(uint64_t current_height);
|
||||
void download_block_headers3(uint64_t start_height, uint64_t current_height);
|
||||
void download_block_headers4(uint64_t start_height, uint64_t current_height);
|
||||
|
||||
bool chainmain_get_by_hash(const hash& id, ChainMain& data) const;
|
||||
|
||||
void api_update_block_found(const ChainMain* data, const PoolBlock* block, bool update_stats_mod = true);
|
||||
void on_external_block(const PoolBlock& block);
|
||||
|
||||
bool get_difficulty_at_height(uint64_t height, difficulty_type& diff);
|
||||
|
||||
@@ -251,6 +262,12 @@ private:
|
||||
mutable uv_rwlock_t m_mergeMiningClientsLock;
|
||||
std::vector<IMergeMiningClient*> m_mergeMiningClients;
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
mutable uv_rwlock_t m_auxJobDonationLock;
|
||||
std::vector<IMergeMiningClient::ChainParameters> m_auxJobDonation;
|
||||
uint64_t m_auxJobDonationLastUpdated = 0;
|
||||
#endif
|
||||
|
||||
mutable uv_rwlock_t m_auxIdLock;
|
||||
std::vector<hash> m_auxId;
|
||||
uint32_t m_auxNonce = 0;
|
||||
|
||||
@@ -153,6 +153,11 @@ Params::Params(int argc, char* const argv[])
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "--nano") == 0) {
|
||||
m_nano = true;
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "--no-autodiff") == 0) {
|
||||
m_autoDiff = false;
|
||||
ok = true;
|
||||
@@ -238,6 +243,13 @@ Params::Params(int argc, char* const argv[])
|
||||
ok = true;
|
||||
}
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
if ((strcmp(argv[i], "--adkf") == 0) && (i + 1 < argc)) {
|
||||
m_authorKeyFile = argv[++i];
|
||||
ok = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ok) {
|
||||
// Wait to avoid log messages overlapping with printf() calls and making a mess on screen
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
@@ -293,6 +305,11 @@ bool Params::valid() const
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_mini && m_nano) {
|
||||
LOGERR(1, "You can't have both --mini and --nano in the command line");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,7 @@ struct Params
|
||||
uint32_t m_maxIncomingPeers = 450;
|
||||
uint32_t m_minerThreads = 0;
|
||||
bool m_mini = false;
|
||||
bool m_nano = false;
|
||||
bool m_autoDiff = true;
|
||||
std::string m_socks5Proxy;
|
||||
bool m_dns = true;
|
||||
@@ -101,6 +102,17 @@ struct Params
|
||||
std::string m_tlsCertKey;
|
||||
#endif
|
||||
bool m_enableStratumHTTP = true;
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
std::string m_authorKeyFile;
|
||||
|
||||
struct AuthorKey {
|
||||
uint8_t pub_key[32];
|
||||
uint8_t expiration_time[8];
|
||||
uint8_t master_key_signature[64];
|
||||
uint8_t priv_key[64];
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace p2pool
|
||||
|
||||
@@ -128,6 +128,11 @@ PoolBlock& PoolBlock::operator=(const PoolBlock& b)
|
||||
m_auxChains = b.m_auxChains;
|
||||
m_auxNonce = b.m_auxNonce;
|
||||
|
||||
m_hashingBlob = b.m_hashingBlob;
|
||||
|
||||
m_powHash = b.m_powHash;
|
||||
m_seed = b.m_seed;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -321,18 +326,32 @@ void PoolBlock::reset_offchain_data()
|
||||
m_auxChains.shrink_to_fit();
|
||||
|
||||
m_auxNonce = 0;
|
||||
|
||||
m_hashingBlob.clear();
|
||||
m_hashingBlob.shrink_to_fit();
|
||||
|
||||
m_powHash = {};
|
||||
m_seed = {};
|
||||
}
|
||||
|
||||
bool PoolBlock::get_pow_hash(RandomX_Hasher_Base* hasher, uint64_t height, const hash& seed_hash, hash& pow_hash, bool force_light_mode)
|
||||
{
|
||||
// Calculate the coinbase tx hash, then the merkle root of all transactions in the block - this merkle root is what goes into the hashing blob
|
||||
|
||||
// Monero transactions are hashed in 3 separate parts, the resulting 3 hashes are then hashed together to get the final result
|
||||
// For the reference, see "calculate_transaction_hash" in Monero's src/cryptonote_basic/cryptonote_format_utils.cpp
|
||||
|
||||
alignas(8) uint8_t hashes[HASH_SIZE * 3];
|
||||
|
||||
uint64_t* second_hash = reinterpret_cast<uint64_t*>(hashes + HASH_SIZE);
|
||||
|
||||
// Second hash is keccak of base rct data (it doesn't exist for the coinbase transaction, so it's a hash of a single 0x00 byte)
|
||||
second_hash[0] = 0x14281e7a9e7836bcull;
|
||||
second_hash[1] = 0x7d818f8229424636ull;
|
||||
second_hash[2] = 0x9165d677b4f71266ull;
|
||||
second_hash[3] = 0x8ac9bc64e0a996ffull;
|
||||
|
||||
// Third hash is null because there is no rct data in the coinbase transaction
|
||||
memset(hashes + HASH_SIZE * 2, 0, HASH_SIZE);
|
||||
|
||||
uint64_t count;
|
||||
@@ -354,6 +373,8 @@ bool PoolBlock::get_pow_hash(RandomX_Hasher_Base* hasher, uint64_t height, const
|
||||
|
||||
const uint8_t* miner_tx = mainchain_data.data() + header_size;
|
||||
hash tmp;
|
||||
|
||||
// "miner_tx_size - 1" because the last byte is 0x00 (base rct data), it goes into the second hash
|
||||
keccak(miner_tx, static_cast<int>(miner_tx_size) - 1, tmp.h);
|
||||
memcpy(hashes, tmp.h, HASH_SIZE);
|
||||
|
||||
@@ -361,6 +382,8 @@ bool PoolBlock::get_pow_hash(RandomX_Hasher_Base* hasher, uint64_t height, const
|
||||
uint8_t* h = reinterpret_cast<uint8_t*>(m_transactions.data());
|
||||
|
||||
keccak(reinterpret_cast<uint8_t*>(hashes), HASH_SIZE * 3, tmp.h);
|
||||
|
||||
// Save the coinbase tx hash into the first element of m_transactions
|
||||
memcpy(h, tmp.h, HASH_SIZE);
|
||||
|
||||
root_hash tmp_root;
|
||||
@@ -371,6 +394,9 @@ bool PoolBlock::get_pow_hash(RandomX_Hasher_Base* hasher, uint64_t height, const
|
||||
|
||||
writeVarint(count, [&blob, &blob_size](uint8_t b) { blob[blob_size++] = b; });
|
||||
|
||||
// cppcheck-suppress danglingLifetime
|
||||
m_hashingBlob.assign(blob, blob + blob_size);
|
||||
|
||||
return hasher->calculate(blob, blob_size, height, seed_hash, pow_hash, force_light_mode);
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -144,7 +144,7 @@ struct PoolBlock
|
||||
|
||||
// Merge mining extra data
|
||||
// Format: vector of (chain ID, chain data) pairs
|
||||
// Chain data format is arbitrary and depends on the merge mined chain's requirements
|
||||
// Chain data always has merge mining hash and difficulty in the beginning, the rest is arbitrary and depends on the merge mined chain's requirements
|
||||
std::map<hash, std::vector<uint8_t>> m_mergeMiningExtra;
|
||||
|
||||
// Arbitrary extra data
|
||||
@@ -173,6 +173,10 @@ struct PoolBlock
|
||||
std::vector<AuxChainData> m_auxChains;
|
||||
uint32_t m_auxNonce;
|
||||
|
||||
std::vector<uint8_t> m_hashingBlob;
|
||||
hash m_powHash;
|
||||
hash m_seed;
|
||||
|
||||
std::vector<uint8_t> serialize_mainchain_data(size_t* header_size = nullptr, size_t* miner_tx_size = nullptr, int* outputs_offset = nullptr, int* outputs_blob_size = nullptr, const uint32_t* nonce = nullptr, const uint32_t* extra_nonce = nullptr) const;
|
||||
std::vector<uint8_t> serialize_sidechain_data() const;
|
||||
|
||||
|
||||
+26
-10
@@ -57,6 +57,7 @@ namespace p2pool {
|
||||
|
||||
static constexpr uint8_t default_consensus_id[HASH_SIZE] = { 34,175,126,231,181,11,104,146,227,153,218,107,44,108,68,39,178,81,4,212,169,4,142,0,177,110,157,240,68,7,249,24 };
|
||||
static constexpr uint8_t mini_consensus_id[HASH_SIZE] = { 57,130,201,26,149,174,199,250,66,80,189,18,108,216,194,220,136,23,63,24,64,113,221,44,219,86,39,163,53,24,126,196 };
|
||||
static constexpr uint8_t nano_consensus_id[HASH_SIZE] = { 171,248,206,148,210,226,114,99,250,145,221,96,13,216,23,63,104,53,129,168,244,80,141,138,157,250,50,54,37,189,5,89 };
|
||||
|
||||
NetworkType SideChain::s_networkType = NetworkType::Invalid;
|
||||
|
||||
@@ -84,6 +85,11 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name)
|
||||
|
||||
LOGINFO(1, log::LightCyan() << "network type = " << type);
|
||||
|
||||
if (m_poolName == "nano") {
|
||||
m_targetBlockTime = 30;
|
||||
m_unclePenalty = 10;
|
||||
}
|
||||
|
||||
if (m_pool && !load_config(m_pool->params().m_sidechainConfig)) {
|
||||
PANIC_STOP();
|
||||
}
|
||||
@@ -118,6 +124,7 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name)
|
||||
|
||||
constexpr char default_config[] = "mainnet\0" "default\0" "\0" "10\0" "100000\0" "2160\0" "20\0";
|
||||
constexpr char mini_config[] = "mainnet\0" "mini\0" "\0" "10\0" "100000\0" "2160\0" "20\0";
|
||||
constexpr char nano_config[] = "mainnet\0" "nano\0" "\0" "30\0" "100000\0" "2160\0" "10\0";
|
||||
|
||||
// Hardcoded default consensus ID
|
||||
if ((s.m_pos == sizeof(default_config) - 1) && (memcmp(buf, default_config, sizeof(default_config) - 1) == 0)) {
|
||||
@@ -127,6 +134,10 @@ SideChain::SideChain(p2pool* pool, NetworkType type, const char* pool_name)
|
||||
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);
|
||||
}
|
||||
// Hardcoded nano consensus ID
|
||||
else if ((s.m_pos == sizeof(nano_config) - 1) && (memcmp(buf, nano_config, sizeof(nano_config) - 1) == 0)) {
|
||||
m_consensusId.assign(nano_consensus_id, nano_consensus_id + HASH_SIZE);
|
||||
}
|
||||
else {
|
||||
#ifdef WITH_RANDOMX
|
||||
const randomx_flags flags = randomx_get_flags();
|
||||
@@ -573,15 +584,13 @@ bool SideChain::add_external_block(PoolBlock& block, std::vector<hash>& missing_
|
||||
LOGWARN(3, "add_external_block: block is built on top of an unknown mainchain block " << block.m_prevId << ", mainchain reorg might've happened");
|
||||
}
|
||||
|
||||
hash seed;
|
||||
if (!m_pool->get_seed(block.m_txinGenHeight, seed)) {
|
||||
if (!m_pool->get_seed(block.m_txinGenHeight, block.m_seed)) {
|
||||
LOGWARN(3, "add_external_block mined by " << block.m_minerWallet << ": couldn't get seed hash for mainchain height " << block.m_txinGenHeight);
|
||||
forget_incoming_block(block);
|
||||
return false;
|
||||
}
|
||||
|
||||
hash pow_hash;
|
||||
if (!block.get_pow_hash(m_pool->hasher(), block.m_txinGenHeight, seed, pow_hash)) {
|
||||
if (!block.get_pow_hash(m_pool->hasher(), block.m_txinGenHeight, block.m_seed, block.m_powHash)) {
|
||||
LOGWARN(3, "add_external_block: couldn't get PoW hash for height = " << block.m_sidechainHeight << ", mainchain height " << block.m_txinGenHeight << ". Ignoring it.");
|
||||
forget_incoming_block(block);
|
||||
return true;
|
||||
@@ -589,7 +598,7 @@ bool SideChain::add_external_block(PoolBlock& block, std::vector<hash>& missing_
|
||||
|
||||
// Check if it has the correct parent and difficulty to go right to monerod for checking
|
||||
MinerData miner_data = m_pool->miner_data();
|
||||
if ((block.m_prevId == miner_data.prev_id) && miner_data.difficulty.check_pow(pow_hash)) {
|
||||
if ((block.m_prevId == miner_data.prev_id) && miner_data.difficulty.check_pow(block.m_powHash)) {
|
||||
LOGINFO(0, log::LightGreen() << "add_external_block: block " << block.m_sidechainId << " has enough PoW for Monero network, submitting it");
|
||||
m_pool->submit_block_async(block.serialize_mainchain_data());
|
||||
}
|
||||
@@ -598,13 +607,13 @@ bool SideChain::add_external_block(PoolBlock& block, std::vector<hash>& missing_
|
||||
if (!m_pool->get_difficulty_at_height(block.m_txinGenHeight, diff)) {
|
||||
LOGWARN(3, "add_external_block: couldn't get mainchain difficulty for height = " << block.m_txinGenHeight);
|
||||
}
|
||||
else if (diff.check_pow(pow_hash)) {
|
||||
else if (diff.check_pow(block.m_powHash)) {
|
||||
LOGINFO(0, log::LightGreen() << "add_external_block: block " << block.m_sidechainId << " has enough PoW for Monero height " << block.m_txinGenHeight << ", submitting it");
|
||||
m_pool->submit_block_async(block.serialize_mainchain_data());
|
||||
}
|
||||
}
|
||||
|
||||
if (!block.m_difficulty.check_pow(pow_hash)) {
|
||||
if (!block.m_difficulty.check_pow(block.m_powHash)) {
|
||||
LOGWARN(3,
|
||||
"add_external_block mined by " << block.m_minerWallet <<
|
||||
": not enough PoW for height = " << block.m_sidechainHeight <<
|
||||
@@ -617,8 +626,8 @@ bool SideChain::add_external_block(PoolBlock& block, std::vector<hash>& missing_
|
||||
|
||||
// Calculate the same hash second time to check if it's an unstable hardware that caused this
|
||||
hash pow_hash2;
|
||||
if (block.get_pow_hash(m_pool->hasher(), block.m_txinGenHeight, seed, pow_hash2, true) && (pow_hash2 != pow_hash)) {
|
||||
LOGERR(0, "UNSTABLE HARDWARE DETECTED: Calculated the same hash twice, got different results: " << pow_hash << " != " << pow_hash2 << " (sidechain id = " << block.m_sidechainId << ')');
|
||||
if (block.get_pow_hash(m_pool->hasher(), block.m_txinGenHeight, block.m_seed, pow_hash2, true) && (pow_hash2 != block.m_powHash)) {
|
||||
LOGERR(0, "UNSTABLE HARDWARE DETECTED: Calculated the same hash twice, got different results: " << block.m_powHash << " != " << pow_hash2 << " (sidechain id = " << block.m_sidechainId << ')');
|
||||
if (block.m_difficulty.check_pow(pow_hash2)) {
|
||||
LOGINFO(3, "add_external_block second result has enough PoW for height = " << block.m_sidechainHeight << ", id = " << block.m_sidechainId);
|
||||
not_enough_pow = false;
|
||||
@@ -630,6 +639,8 @@ bool SideChain::add_external_block(PoolBlock& block, std::vector<hash>& missing_
|
||||
}
|
||||
}
|
||||
|
||||
m_pool->on_external_block(block);
|
||||
|
||||
bool block_found = false;
|
||||
|
||||
missing_blocks.clear();
|
||||
@@ -1062,7 +1073,7 @@ void SideChain::print_status(bool obtain_sidechain_lock) const
|
||||
"\nMonero node = " << m_pool->current_host().m_displayName <<
|
||||
"\nMain chain height = " << m_pool->block_template().height() <<
|
||||
"\nMain chain hashrate = " << log::Hashrate(network_hashrate) <<
|
||||
"\nSide chain ID = " << (is_default() ? "default" : (is_mini() ? "mini" : m_consensusIdDisplayStr.c_str())) <<
|
||||
"\nSide chain ID = " << (is_default() ? "default" : (is_mini() ? "mini" : (is_nano() ? "nano" : m_consensusIdDisplayStr.c_str()))) <<
|
||||
"\nSide chain height = " << tip_height + 1 <<
|
||||
"\nSide chain hashrate = " << log::Hashrate(pool_hashrate) <<
|
||||
(hashrate_est ? "\nYour hashrate (pool-side) = " : "") << (hashrate_est ? log::Hashrate(hashrate_est) : log::Hashrate()) <<
|
||||
@@ -1185,6 +1196,11 @@ bool SideChain::is_mini() const
|
||||
return (memcmp(m_consensusId.data(), mini_consensus_id, HASH_SIZE) == 0);
|
||||
}
|
||||
|
||||
bool SideChain::is_nano() const
|
||||
{
|
||||
return (memcmp(m_consensusId.data(), nano_consensus_id, HASH_SIZE) == 0);
|
||||
}
|
||||
|
||||
uint64_t SideChain::bottom_height(const PoolBlock* tip) const
|
||||
{
|
||||
if (!tip) {
|
||||
|
||||
@@ -79,6 +79,7 @@ public:
|
||||
[[nodiscard]] uint64_t last_updated() const;
|
||||
[[nodiscard]] bool is_default() const;
|
||||
[[nodiscard]] bool is_mini() const;
|
||||
[[nodiscard]] bool is_nano() const;
|
||||
[[nodiscard]] uint64_t bottom_height(const PoolBlock* tip) const;
|
||||
|
||||
[[nodiscard]] const PoolBlock* chainTip() const { return m_chainTip; }
|
||||
|
||||
@@ -891,6 +891,26 @@ void StratumServer::update_hashrate_data(uint64_t hashes, uint64_t timestamp)
|
||||
if (hashes) {
|
||||
m_cumulativeHashes += hashes;
|
||||
++m_totalStratumShares;
|
||||
|
||||
// P2Pool-nano warning
|
||||
#ifndef P2POOL_LOG_DISABLE
|
||||
// Check the hashrate when enough shares is found
|
||||
if (((m_totalStratumShares & 63) == 0) && m_pool->side_chain().is_nano()) {
|
||||
const HashrateData& head = m_hashrateData[m_hashrateDataHead];
|
||||
const HashrateData& tail = m_hashrateData[m_hashrateDataTail_24h];
|
||||
|
||||
const int64_t dt = static_cast<int64_t>(head.m_timestamp - tail.m_timestamp);
|
||||
|
||||
if (dt > 0) {
|
||||
const uint64_t total_hashes = head.m_cumulativeHashes - tail.m_cumulativeHashes;
|
||||
const uint64_t hashrate = total_hashes / dt;
|
||||
|
||||
if (hashrate > 30000) {
|
||||
LOGINFO(0, log::LightRed() << "Your hashrate is " << log::Hashrate(hashrate) << ". Please switch from P2Pool-nano to P2Pool-mini or P2Pool-main. P2Pool-nano is recommended only for small-scale miners.");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // P2POOL_LOG_DISABLE
|
||||
}
|
||||
|
||||
HashrateData* data = m_hashrateData;
|
||||
@@ -1533,6 +1553,7 @@ void StratumServer::api_update_local_stats(uint64_t timestamp)
|
||||
<< ",\"connections\":" << connections
|
||||
<< ",\"incoming_connections\":" << incoming_connections
|
||||
<< ",\"block_reward_share_percent\":" << block_reward_share_percent
|
||||
<< ",\"wallet\":\"" << m_pool->params().m_wallet << '"'
|
||||
<< ",\"workers\":[";
|
||||
|
||||
const difficulty_type pool_diff = m_pool->side_chain().difficulty();
|
||||
|
||||
@@ -60,6 +60,8 @@ const char* VERSION = "v" STR2(P2POOL_VERSION_MAJOR) "." STR2(P2POOL_VERSION_MIN
|
||||
#endif
|
||||
" on " __DATE__ ")";
|
||||
|
||||
const uint8_t ED25519_MASTER_PUBLIC_KEY[32] = {51,175,37,73,203,241,188,115,195,255,123,53,218,120,90,74,186,240,82,178,67,139,124,91,180,106,188,181,187,51,236,10};
|
||||
|
||||
std::string DATA_DIR;
|
||||
|
||||
SoftwareID get_software_id(uint32_t value)
|
||||
|
||||
+13
-2
@@ -35,13 +35,15 @@
|
||||
namespace p2pool {
|
||||
|
||||
#define P2POOL_VERSION_MAJOR 4
|
||||
#define P2POOL_VERSION_MINOR 5
|
||||
#define P2POOL_VERSION_MINOR 7
|
||||
#define P2POOL_VERSION_PATCH 0
|
||||
|
||||
constexpr uint32_t P2POOL_VERSION = (P2POOL_VERSION_MAJOR << 16) | (P2POOL_VERSION_MINOR << 8) | P2POOL_VERSION_PATCH;
|
||||
|
||||
extern const char* VERSION;
|
||||
|
||||
extern const uint8_t ED25519_MASTER_PUBLIC_KEY[32];
|
||||
|
||||
extern std::string DATA_DIR;
|
||||
|
||||
enum class SoftwareID : uint32_t {
|
||||
@@ -67,7 +69,16 @@ template<typename T>
|
||||
struct ScopeGuard : public nocopy_nomove
|
||||
{
|
||||
explicit FORCEINLINE ScopeGuard(T&& handler) : m_handler(std::move(handler)) {}
|
||||
FORCEINLINE ~ScopeGuard() { m_handler(); }
|
||||
|
||||
FORCEINLINE ~ScopeGuard()
|
||||
{
|
||||
// Because the handler can throw an exception, and we don't want exceptions in a destructor
|
||||
try {
|
||||
m_handler();
|
||||
}
|
||||
catch(...) {
|
||||
}
|
||||
}
|
||||
|
||||
T m_handler;
|
||||
};
|
||||
|
||||
@@ -22,14 +22,21 @@ if (CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
include(cmake/msvc_libs.cmake)
|
||||
endif()
|
||||
|
||||
add_subdirectory(../external/src/RandomX RandomX)
|
||||
set(LIBS ${LIBS} randomx)
|
||||
if (STATIC_LIBS AND WIN32 AND (CMAKE_CXX_COMPILER_ID MATCHES Clang))
|
||||
set(LIBS ${LIBS} "${CMAKE_SOURCE_DIR}/../build/external/src/RandomX/librandomx.a")
|
||||
else()
|
||||
add_subdirectory(../external/src/RandomX RandomX)
|
||||
set(LIBS ${LIBS} randomx)
|
||||
endif()
|
||||
|
||||
add_definitions(-DWITH_RANDOMX)
|
||||
|
||||
add_subdirectory(cmake/ssl)
|
||||
include_directories(../external/src/grpc/third_party/boringssl-with-bazel/src/include)
|
||||
add_definitions(-DWITH_TLS)
|
||||
|
||||
add_definitions(-DWITH_MERGE_MINING_DONATION)
|
||||
|
||||
add_definitions(-DP2POOL_UNIT_TESTS)
|
||||
add_definitions(-DP2POOL_SIDECHAIN_EXTRA_1=1)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user