Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d8ddaf80c8 | |||
| 2dc091f3d4 | |||
| 55cd2c9ae1 | |||
| 53cecac65b | |||
| d9de512b92 | |||
| 1bdf562967 | |||
| d0daa6ec41 | |||
| 1eb93fcd6b | |||
| 1cb4940960 | |||
| d5025965b4 | |||
| 6aba1edaf8 | |||
| 1166f31d07 | |||
| 3d2c9910f8 | |||
| 3584910baa | |||
| 8230040b76 | |||
| de28201edc | |||
| d9cea1cfc3 | |||
| 321d698be5 | |||
| 44a668cb15 | |||
| 8151a5a537 | |||
| b81a582154 | |||
| ee931ee178 | |||
| dbf0e58ee5 | |||
| 86e9e90744 | |||
| dec45532f8 |
@@ -286,6 +286,64 @@ jobs:
|
||||
build/*.log
|
||||
build/data/
|
||||
|
||||
sync-test-ubuntu-tysan:
|
||||
if: false # disabled because it generates a flood of type aliasing errors
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y git build-essential cmake libuv1-dev libzmq3-dev libgss-dev libcurl4-openssl-dev libidn2-0-dev
|
||||
|
||||
- name: Install clang
|
||||
run: |
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh 21 all
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Build p2pool
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=clang-21 -DCMAKE_CXX_COMPILER=clang++-21 -DDEV_TEST_SYNC=ON -DDEV_DEBUG=ON -DDEV_WITH_TYSAN=ON -DWITH_LTO=OFF -DWITH_INDEXED_HASHES=ON -DCMAKE_POLICY_VERSION_MINIMUM="3.5"
|
||||
make -j$(nproc) p2pool
|
||||
|
||||
- name: Run p2pool
|
||||
run: |
|
||||
cd build
|
||||
mkdir data
|
||||
python ../tests/src/stratum_dummy.py 1 &
|
||||
python ../tests/src/stratum_dummy.py 2 &
|
||||
python ../tests/src/stratum_dummy.py 3 &
|
||||
sudo sysctl vm.mmap_rnd_bits=28
|
||||
TYSAN_OPTIONS=print_stacktrace=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 ${{ secrets.MM_PARAMS }} --out-peers 50 --data-api data --local-api --loglevel 6 --light-mode 2> stderr.log
|
||||
|
||||
- name: Check synchronization
|
||||
run: |
|
||||
cd build
|
||||
grep 'Synchronization finished successfully' p2pool.log
|
||||
|
||||
- name: Check p2pool.log for errors
|
||||
run: |
|
||||
cd build
|
||||
../scripts/workflows/test-sync-check.sh
|
||||
|
||||
- name: Archive p2pool.log
|
||||
if: '!cancelled()'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: p2pool_ubuntu_data_tysan
|
||||
path: |
|
||||
build/*.log
|
||||
build/data/
|
||||
|
||||
sync-test-macos:
|
||||
|
||||
timeout-minutes: 120
|
||||
|
||||
@@ -27,6 +27,7 @@ option(DEV_WITH_TSAN "[Developer only] Compile with thread sanitizer" OFF)
|
||||
option(DEV_WITH_MSAN "[Developer only] Compile with memory sanitizer" OFF)
|
||||
option(DEV_WITH_UBSAN "[Developer only] Compile with undefined behavior sanitizer" OFF)
|
||||
option(DEV_WITH_ASAN "[Developer only] Compile with address sanitizer" OFF)
|
||||
option(DEV_WITH_TYSAN "[Developer only] Compile with type sanitizer" OFF)
|
||||
option(DEV_CLANG_TIDY "[Developer only] Compile for clang-tidy" OFF)
|
||||
option(DEV_TRACK_MEMORY "[Developer only] Track memory allocations" OFF)
|
||||
option(DEV_DEBUG "[Developer only] Compile a debug build" OFF)
|
||||
|
||||
@@ -2,7 +2,13 @@
|
||||
|
||||
Decentralized pool for Monero mining.
|
||||
|
||||
Pool status and monitoring pages can be found at https://p2pool.io/, https://p2pool.io/mini/ and https://p2pool.observer/, https://mini.p2pool.observer/
|
||||
Pool status and monitoring pages can be found at:
|
||||
|
||||
|P2Pool||
|
||||
|-|-|
|
||||
|main|https://p2pool.io/ <br> https://p2pool.observer/|
|
||||
|mini|https://p2pool.io/mini/ <br> https://mini.p2pool.observer/|
|
||||
|nano|https://p2pool.io/nano/ <br> https://nano.p2pool.observer/|
|
||||
|
||||
These are 3rd-party pages. If they are down, it doesn't mean there is a problem with P2Pool itself - it keeps mining always thanks to its decentralized nature.
|
||||
|
||||
@@ -92,8 +98,15 @@ In order to continue mining on P2Pool, you must update both Monero and P2Pool so
|
||||
- In order to mine on P2Pool, a synced Monero node using monerod v0.18.0.0 or newer is required. If you don't currently have one, you can download the [official Monero binaries](https://www.getmonero.org/downloads/), start `monerod` on your PC and wait until it's fully synced. Advanced Monero node setup instructions are [here](https://sethforprivacy.com/guides/run-a-monero-node-advanced/).
|
||||
- It is highly recommended that you create a separate restricted user account (in your OS) for mining. While P2Pool has been battle-tested for a long time now, any software may have unknown bugs/vulnerabilities.
|
||||
- You can mine to a primary wallet address (the one starting with `4`) for mining. If you want to mine to a subaddress, you will need to provide both the main address (starting with 4) and the subaddress (starting with 8) using `--wallet` and `--subaddress` command line parameters.
|
||||
- You can add the `--mini` parameter to your P2Pool command to connect to the **p2pool-mini** sidechain. Note that it will also change the default p2p port from 37889 to 37888.
|
||||
- Check that ports 18080 (Monero p2p port) and 37889/37888 (P2Pool/P2Pool mini p2p port) are open in your firewall to ensure better connectivity. If you're mining from a computer behind NAT (like a router) you could consider forwarding the ports to your local machine.
|
||||
- You can add the `--mini` or `--nano` parameter to your P2Pool command to connect to the respective sidechain.
|
||||
> [!NOTE]
|
||||
>
|
||||
> You cannot use both `--mini` and `--nano` together
|
||||
>
|
||||
> Using `--mini` will change the p2p port to 37888.
|
||||
>
|
||||
> Using `--nano` will change the p2p port to 37890.
|
||||
- Check that ports 18080 (Monero p2p port) and 37889/37888/37890 (P2Pool default/mini/nano p2p port) are open in your firewall to ensure better connectivity. If you're mining from a computer behind NAT (like a router) you could consider forwarding the ports to your local machine.
|
||||
- You can connect multiple miners to the same P2Pool node. The more the better!
|
||||
- The steps below assume that you run everything on the same machine. If it's not the case, change `127.0.0.1` to appropriate IP addresses for your setup.
|
||||
- It is highly recommended to create a new mainnet wallet for P2Pool mining because **wallet addresses are public on P2Pool**.
|
||||
@@ -108,7 +121,7 @@ In order to continue mining on P2Pool, you must update both Monero and P2Pool so
|
||||
|
||||
### GUI for P2Pool
|
||||
|
||||
- [Gupax](https://github.com/hinto-janai/gupax) project aims to provide an easy to use cross-platform GUI to configure and run P2Pool & [XMRig](https://github.com/xmrig/xmrig).
|
||||
- [Gupax](https://github.com/gupax-io/gupax) project aims to provide an easy to use cross-platform GUI to configure and run P2Pool & [XMRig](https://github.com/xmrig/xmrig).
|
||||
|
||||
### Merge mining
|
||||
|
||||
@@ -152,7 +165,7 @@ Note that Tari will be mined in solo mode (only full Tari blocks can be mined fo
|
||||
```
|
||||
sudo sysctl vm.nr_hugepages=3072
|
||||
```
|
||||
4. Check that ports 18080 (Monero p2p port) and 37889/37888 (P2Pool/P2Pool mini p2p port) are open in your local firewall to ensure better connectivity.
|
||||
4. Check that ports 18080 (Monero p2p port) and 37889/37888/37890 (P2Pool default/mini/nano p2p port) are open in your local firewall to ensure better connectivity.
|
||||
5. Start `monerod` with the following command/options:
|
||||
```
|
||||
./monerod --zmq-pub tcp://127.0.0.1:18083 --out-peers 32 --in-peers 64 --add-priority-node=p2pmd.xmrvsbeast.com:18080 --add-priority-node=nodes.hashvault.pro:18080 --enforce-dns-checkpointing --enable-dns-blocklist
|
||||
|
||||
+5
-1
@@ -113,6 +113,10 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
set(GENERAL_FLAGS "${GENERAL_FLAGS} -mfix-cortex-a53-835769")
|
||||
endif()
|
||||
|
||||
if (DEV_WITH_TYSAN)
|
||||
set(GENERAL_FLAGS "${GENERAL_FLAGS} -fno-omit-frame-pointer -fsanitize=type")
|
||||
endif()
|
||||
|
||||
set(WARNING_FLAGS "-Wall -Wextra -Wno-unused-function -Wno-undefined-internal -Wno-unknown-warning-option -Wno-nan-infinity-disabled -Wunreachable-code-aggressive -Wmissing-prototypes -Wmissing-variable-declarations -Werror")
|
||||
|
||||
if (NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 20))
|
||||
@@ -123,7 +127,7 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES Clang)
|
||||
set(WARNING_FLAGS "-w")
|
||||
endif()
|
||||
|
||||
if (DEV_WITH_MSAN OR DEV_DEBUG OR (CMAKE_BUILD_TYPE STREQUAL "Debug") OR (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
|
||||
if (DEV_WITH_MSAN OR DEV_WITH_TYSAN OR DEV_DEBUG OR (CMAKE_BUILD_TYPE STREQUAL "Debug") OR (CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"))
|
||||
add_definitions(-DDEBUG_BUILD)
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(OPTIMIZATION_FLAGS "-O0")
|
||||
|
||||
@@ -3,7 +3,7 @@ set(CMAKE_CROSSCOMPILING TRUE)
|
||||
|
||||
set(CMAKE_SYSTEM_PROCESSOR aarch64)
|
||||
|
||||
set(CMAKE_C_COMPILER /usr/local/bin/aarch64-apple-darwin25-clang)
|
||||
set(CMAKE_CXX_COMPILER /usr/local/bin/aarch64-apple-darwin25-clang++)
|
||||
set(CMAKE_ASM_COMPILER /usr/local/bin/aarch64-apple-darwin25-as)
|
||||
set(CMAKE_STRIP /usr/local/bin/aarch64-apple-darwin25-strip)
|
||||
set(CMAKE_C_COMPILER /usr/local/bin/aarch64-apple-darwin25.1-clang)
|
||||
set(CMAKE_CXX_COMPILER /usr/local/bin/aarch64-apple-darwin25.1-clang++)
|
||||
set(CMAKE_ASM_COMPILER /usr/local/bin/aarch64-apple-darwin25.1-as)
|
||||
set(CMAKE_STRIP /usr/local/bin/aarch64-apple-darwin25.1-strip)
|
||||
|
||||
@@ -3,7 +3,7 @@ set(CMAKE_CROSSCOMPILING TRUE)
|
||||
|
||||
set(CMAKE_SYSTEM_PROCESSOR x86_64)
|
||||
|
||||
set(CMAKE_C_COMPILER /usr/local/bin/x86_64-apple-darwin25-clang)
|
||||
set(CMAKE_CXX_COMPILER /usr/local/bin/x86_64-apple-darwin25-clang++)
|
||||
set(CMAKE_ASM_COMPILER /usr/local/bin/x86_64-apple-darwin25-as)
|
||||
set(CMAKE_STRIP /usr/local/bin/x86_64-apple-darwin25-strip)
|
||||
set(CMAKE_C_COMPILER /usr/local/bin/x86_64-apple-darwin25.1-clang)
|
||||
set(CMAKE_CXX_COMPILER /usr/local/bin/x86_64-apple-darwin25.1-clang++)
|
||||
set(CMAKE_ASM_COMPILER /usr/local/bin/x86_64-apple-darwin25.1-as)
|
||||
set(CMAKE_STRIP /usr/local/bin/x86_64-apple-darwin25.1-strip)
|
||||
|
||||
@@ -33,7 +33,7 @@ docker compose up
|
||||
```
|
||||
|
||||
#### Optional
|
||||
* Open ports 18080 (Monero p2p port) and 37889 (P2Pool p2p port) or 37888 (P2Pool-mini p2p port) in your firewall to ensure better connectivity. If you're mining from a computer behind NAT (like a router) you could consider forwarding the ports to your local machine
|
||||
* Open ports 18080 (Monero p2p port) and 37889/37888/37890 (P2Pool default/mini/nano p2p port) in your firewall to ensure better connectivity. If you're mining from a computer behind NAT (like a router) you could consider forwarding the ports to your local machine
|
||||
* An XMRig CPU miner is included by default, but you can connect additional miners to this same p2pool node using port 3333 (or alternate if configured) when you set it as "exposed" in the configuration
|
||||
* Configure your kernel for maximum mining performance: [XMRig RandomX Optimization Guide](https://xmrig.com/docs/miner/randomx-optimization-guide)
|
||||
* Many optional configurations and customizations are available by running './configure'
|
||||
@@ -54,4 +54,5 @@ Change to p2pool/docker-compose directory <br />
|
||||
Stop and remove all containers: ```docker compose down``` <br />
|
||||
Remove the p2pool data: ```docker volume rm p2pool``` <br />
|
||||
Remove the p2pool-mini data: ```docker volume rm p2pool-mini``` <br />
|
||||
Remove the p2pool-nano data: ```docker volume rm p2pool-nano``` <br />
|
||||
Remove the monero data: ```docker volume rm monero```
|
||||
|
||||
@@ -37,7 +37,8 @@ class P2PoolHelpBox(HelpBoxBase):
|
||||
"P2Pool Sidechain:": [
|
||||
"Which P2Pool sidechain to mine on",
|
||||
" use main for faster miners",
|
||||
" use mini for slower miners",
|
||||
" use mini for slow miners (>30kH/s)",
|
||||
" use nano for slower miners (<30kH/s)",
|
||||
],
|
||||
"Enable Server Statistics": [
|
||||
"Provide access to your P2Pool server statictics via a web interface",
|
||||
@@ -364,7 +365,7 @@ class P2PoolConfigForm(ConfigFormBase):
|
||||
self.sidechain = self.add(
|
||||
npyscreen.TitleSelectOne,
|
||||
name="P2Pool Sidechain:",
|
||||
values=["main", "mini"],
|
||||
values=["main", "mini", "nano"],
|
||||
scroll_exit=True,
|
||||
max_height=2,
|
||||
value=[
|
||||
|
||||
@@ -7,10 +7,12 @@ networks:
|
||||
|
||||
volumes:
|
||||
p2pool:
|
||||
{% if sidechain[0] == 0 %}
|
||||
name: p2pool
|
||||
{% else %}
|
||||
{% if sidechain[0] == 1 %}
|
||||
name: p2pool-mini
|
||||
{% elif sidechain[0] == 2 %}
|
||||
name: p2pool-nano
|
||||
{% else %}
|
||||
name: p2pool
|
||||
{% endif %}
|
||||
|
||||
{% if configure_monero == True %}
|
||||
@@ -55,6 +57,8 @@ services:
|
||||
--loglevel {{ p2pool_log_level | int }}
|
||||
{% if sidechain[0] == 1 %}
|
||||
--mini
|
||||
{% elif sidechain[0] == 2 %}
|
||||
--nano
|
||||
{% endif %}
|
||||
{% if enable_autodiff == False %}
|
||||
--no-autodiff
|
||||
|
||||
+20
-2
@@ -13,6 +13,7 @@
|
||||
--light-mode Don't allocate RandomX dataset, saves 2GB of RAM
|
||||
--loglevel Verbosity of the log, integer number between 0 and 6
|
||||
--data-dir Path to store general p2pool files (log, cache, peer data, etc.), default is current directory
|
||||
--log-file Path to the log file, default is "p2pool.log" in p2pool's working directory
|
||||
--sidechain-config Name of the p2pool sidechain parameters file (only use it if you run your own sidechain)
|
||||
--data-api Path to the p2pool JSON data (use it in tandem with an external web-server). Not affected by --data-dir setting!
|
||||
--local-api Enable /local/ path in api path for Stratum Server and built-in miner statistics
|
||||
@@ -23,8 +24,8 @@
|
||||
--out-peers N Maximum number of outgoing connections for p2p server (any value between 10 and 450)
|
||||
--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
|
||||
--mini Connect to p2pool-mini sidechain. Note that it will also change default p2p port from 37889 to 37888. Cannot be used with --nano.
|
||||
--nano Connect to p2pool-nano sidechain. Note that it will also change default p2p port from 37889 to 37890. Cannot be used with --mini.
|
||||
--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
|
||||
@@ -43,6 +44,7 @@
|
||||
--full-validation Enables full share validation / increases CPU usage
|
||||
--onion-address Tell other peers to use this .onion address to connect to this node through TOR
|
||||
--no-clearnet-p2p Forces P2P server to listen on 127.0.0.1 and to not connect to clearnet IPs
|
||||
--params-file File name to load parameters from. It can't be used together with any other command line parameters
|
||||
```
|
||||
|
||||
### Example command line
|
||||
@@ -51,6 +53,22 @@
|
||||
p2pool.exe --host 127.0.0.1 --rpc-port 18081 --zmq-port 18083 --wallet YOUR_WALLET_ADDRESS --stratum 0.0.0.0:3333 --p2p 0.0.0.0:37889
|
||||
```
|
||||
|
||||
### Example command line (params file)
|
||||
|
||||
```
|
||||
p2pool.exe --params-file params.conf
|
||||
```
|
||||
|
||||
params.conf
|
||||
```
|
||||
# IP of your node
|
||||
host = 127.0.0.1
|
||||
wallet = YOUR_WALLET_ADDRESS
|
||||
data-api = "/path/to/api/folder" # use quotes if you have spaces in the path
|
||||
loglevel = 4
|
||||
mini = 1
|
||||
```
|
||||
|
||||
### Example command line (mining to a subaddress)
|
||||
|
||||
```
|
||||
|
||||
@@ -256,7 +256,7 @@ It's highly recommended to create a new wallet for mining because wallet address
|
||||
<details><summary>Setup P2Pool node</summary>
|
||||
<ul>
|
||||
<li>Download the latest P2Pool <a href="https://github.com/SChernykh/p2pool/releases/latest" target="_blank">release</a>
|
||||
<li>[Optional] Open port <span>37889</span> (P2Pool port) or <span>37888</span> (P2Pool mini port) in your firewall to ensure better connectivity
|
||||
<li>[Optional] Open port <span>37889</span> (P2Pool p2p port) in your firewall to ensure better connectivity
|
||||
<li>Run <span>./p2pool --host 127.0.0.1 --wallet YOUR_WALLET_ADDRESS</span>
|
||||
<li>It should take no more than 5-10 minutes to synchronize
|
||||
</ul></details>
|
||||
@@ -274,6 +274,7 @@ It's highly recommended to create a new wallet for mining because wallet address
|
||||
<ul>
|
||||
<li>You can enter your wallet address at <a href="https://p2pool.observer/" target="_blank">P2Pool Observer</a>
|
||||
<li>P2Pool Observer for P2Pool mini can be found <a href="https://mini.p2pool.observer/" target="_blank">here</a>
|
||||
<li>P2Pool Observer for P2Pool nano can be found <a href="https://nano.p2pool.observer/" target="_blank">here</a>
|
||||
<li>You will find your wallet's statistics there only after you've mined at least 1 P2Pool share
|
||||
</ul>
|
||||
</details>
|
||||
@@ -300,7 +301,7 @@ P2Pool is a decentralized community, there is no dedicated support. You can reac
|
||||
<li><span style="font-size:2rem;color:#e09000;">I have been mining for several hours and still got no rewards?</span>
|
||||
<ul><li>P2Pool doesn't work exactly like regular pools - there's no "pending balance" here. You need to find a pool share first and then wait for P2Pool to find a Monero block. You'll get a payout to your XMR wallet as soon as a block is found and you have shares in PPLNS window. It can take several days to a week to find a share if your hashrate is low. Type "status" command in P2Pool console or visit <a href="https://p2pool.observer/" target="_blank">P2Pool observer</a> to check your progress.</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">I am mining but I can't find any shares</span>
|
||||
<ul><li>First check for any warnings and errors in P2Pool console and logs. If everything works fine, you can check the <a href="https://p2pool.observer/calculate-share-time" target="_blank">average share time calculator</a> to get an idea how often you should find a share with your hashrate. If this time is more than 1 day, it's recommended to switch to P2Pool mini by adding <span style="color:#808080;">--mini</span> to P2Pool command line.</ul><br>
|
||||
<ul><li>First check for any warnings and errors in P2Pool console and logs. If everything works fine, you can check the <a href="https://p2pool.observer/calculate-share-time" target="_blank">average share time calculator</a> to get an idea how often you should find a share with your hashrate. If this time is more than 1 day, it's recommended to switch to either P2Pool mini or nano by adding <span style="color:#808080;">--mini</span> or <span style="color:#808080;">--nano</span> to P2Pool command line.</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">I get an error "monerod RPC ... is incompatible, update to RPC >= v3.8"</span>
|
||||
<ul><li>Use monerod v0.18.0.0 or newer</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">I get warnings "peer ... is ahead on mainchain (height ..., your height ...). Is your monerod stuck or lagging?"</span>
|
||||
|
||||
@@ -256,7 +256,7 @@ It's highly recommended to create a new wallet for mining because wallet address
|
||||
<details><summary>Setup P2Pool node</summary>
|
||||
<ul>
|
||||
<li>Download the latest P2Pool <a href="https://github.com/SChernykh/p2pool/releases/latest" target="_blank">release</a>
|
||||
<li>[Optional] Open port <span>37889</span> (P2Pool port) or <span>37888</span> (P2Pool mini port) in your firewall to ensure better connectivity
|
||||
<li>[Optional] Open port <span>37888</span> (P2Pool mini p2p port) in your firewall to ensure better connectivity
|
||||
<li>Run <span>./p2pool --host 127.0.0.1 --wallet YOUR_WALLET_ADDRESS --mini</span>
|
||||
<li>It should take no more than 5-10 minutes to synchronize
|
||||
</ul></details>
|
||||
@@ -274,6 +274,7 @@ It's highly recommended to create a new wallet for mining because wallet address
|
||||
<ul>
|
||||
<li>You can enter your wallet address at <a href="https://p2pool.observer/" target="_blank">P2Pool Observer</a>
|
||||
<li>P2Pool Observer for P2Pool mini can be found <a href="https://mini.p2pool.observer/" target="_blank">here</a>
|
||||
<li>P2Pool Observer for P2Pool nano can be found <a href="https://nano.p2pool.observer/" target="_blank">here</a>
|
||||
<li>You will find your wallet's statistics there only after you've mined at least 1 P2Pool share
|
||||
</ul>
|
||||
</details>
|
||||
@@ -300,7 +301,7 @@ P2Pool is a decentralized community, there is no dedicated support. You can reac
|
||||
<li><span style="font-size:2rem;color:#e09000;">I have been mining for several hours and still got no rewards?</span>
|
||||
<ul><li>P2Pool doesn't work exactly like regular pools - there's no "pending balance" here. You need to find a pool share first and then wait for P2Pool to find a Monero block. You'll get a payout to your XMR wallet as soon as a block is found and you have shares in PPLNS window. It can take several days to a week to find a share if your hashrate is low. Type "status" command in P2Pool console or visit <a href="https://mini.p2pool.observer/" target="_blank">P2Pool observer</a> to check your progress.</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">I am mining but I can't find any shares</span>
|
||||
<ul><li>First check for any warnings and errors in P2Pool console and logs. If everything works fine, you can check the <a href="https://p2pool.observer/calculate-share-time" target="_blank">average share time calculator</a> to get an idea how often you should find a share with your hashrate. If this time is more than 1 day, it's recommended to switch to P2Pool mini by adding <span style="color:#808080;">--mini</span> to P2Pool command line.</ul><br>
|
||||
<ul><li>First check for any warnings and errors in P2Pool console and logs. If everything works fine, you can check the <a href="https://p2pool.observer/calculate-share-time" target="_blank">average share time calculator</a> to get an idea how often you should find a share with your hashrate. If this time is more than 1 day, it's recommended to switch to P2Pool mini or nano by adding <span style="color:#808080;">--mini</span> or <span style="color:#808080;">--nano</span> to P2Pool command line.</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">I get an error "monerod RPC ... is incompatible, update to RPC >= v3.8"</span>
|
||||
<ul><li>Use monerod v0.18.0.0 or newer</ul><br>
|
||||
<li><span style="font-size:2rem;color:#e09000;">I get warnings "peer ... is ahead on mainchain (height ..., your height ...). Is your monerod stuck or lagging?"</span>
|
||||
|
||||
@@ -259,7 +259,7 @@ It's highly recommended to create a new wallet for mining because wallet address
|
||||
<details><summary>Setup P2Pool node</summary>
|
||||
<ul>
|
||||
<li>Download the latest P2Pool <a href="https://github.com/SChernykh/p2pool/releases/latest" target="_blank">release</a>
|
||||
<li>[Optional] Open port <span>37889</span> (P2Pool port) or <span>37890</span> (P2Pool nano port) in your firewall to ensure better connectivity
|
||||
<li>[Optional] Open port <span>37890</span> (P2Pool nano p2p port) in your firewall to ensure better connectivity
|
||||
<li>Run <span>./p2pool --host 127.0.0.1 --wallet YOUR_WALLET_ADDRESS --nano</span>
|
||||
<li>It should take no more than 5-10 minutes to synchronize
|
||||
</ul></details>
|
||||
@@ -276,6 +276,7 @@ It's highly recommended to create a new wallet for mining because wallet address
|
||||
<details><summary>Checking your progress</summary>
|
||||
<ul>
|
||||
<li>You can enter your wallet address at <a href="https://p2pool.observer/" target="_blank">P2Pool Observer</a>
|
||||
<li>P2Pool Observer for P2Pool mini can be found <a href="https://mini.p2pool.observer/" target="_blank">here</a>
|
||||
<li>P2Pool Observer for P2Pool nano can be found <a href="https://nano.p2pool.observer/" target="_blank">here</a>
|
||||
<li>You will find your wallet's statistics there only after you've mined at least 1 P2Pool share
|
||||
</ul>
|
||||
|
||||
Vendored
+1
-1
Submodule external/src/grpc updated: 0a4737ced1...b40fe4ffc4
@@ -1,5 +1,5 @@
|
||||
diff --git a/crypto/rand/windows.cc b/crypto/rand/windows.cc
|
||||
index 59df467e7..aa5ac076c 100644
|
||||
index 6a93a2d84..f75112b4f 100644
|
||||
--- a/crypto/rand/windows.cc
|
||||
+++ b/crypto/rand/windows.cc
|
||||
@@ -24,6 +24,7 @@
|
||||
@@ -10,10 +10,10 @@ index 59df467e7..aa5ac076c 100644
|
||||
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
|
||||
!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
@@ -57,16 +58,40 @@ void CRYPTO_sysrand(uint8_t *out, size_t requested) {
|
||||
@@ -57,16 +58,39 @@ void CRYPTO_sysrand(uint8_t *out, size_t requested) {
|
||||
// See: https://learn.microsoft.com/en-us/windows/win32/seccng/processprng
|
||||
typedef BOOL (WINAPI *ProcessPrngFunction)(PBYTE pbData, SIZE_T cbData);
|
||||
static ProcessPrngFunction g_processprng_fn = NULL;
|
||||
static ProcessPrngFunction g_processprng_fn = nullptr;
|
||||
+static HCRYPTPROV g_hCryptProv = 0;
|
||||
+
|
||||
+static BOOL WINAPI wrapper_CryptGenRandom(PBYTE pbData, SIZE_T cbData)
|
||||
@@ -23,19 +23,17 @@ index 59df467e7..aa5ac076c 100644
|
||||
|
||||
static void init_processprng(void) {
|
||||
HMODULE hmod = LoadLibraryW(L"bcryptprimitives");
|
||||
- if (hmod == NULL) {
|
||||
- if (hmod == nullptr) {
|
||||
- abort();
|
||||
- }
|
||||
- g_processprng_fn = (ProcessPrngFunction)GetProcAddress(hmod, "ProcessPrng");
|
||||
- if (g_processprng_fn == NULL) {
|
||||
- abort();
|
||||
+
|
||||
+ if (hmod) {
|
||||
+ g_processprng_fn = (ProcessPrngFunction)GetProcAddress(hmod, "ProcessPrng");
|
||||
+ if (g_processprng_fn) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
- g_processprng_fn = (ProcessPrngFunction)GetProcAddress(hmod, "ProcessPrng");
|
||||
- if (g_processprng_fn == nullptr) {
|
||||
- abort();
|
||||
+
|
||||
+ if (CryptAcquireContext(&g_hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
|
||||
+ g_processprng_fn = &wrapper_CryptGenRandom;
|
||||
@@ -51,7 +49,7 @@ index 59df467e7..aa5ac076c 100644
|
||||
+ else {
|
||||
+ err = GetLastError();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ abort();
|
||||
}
|
||||
|
||||
@@ -4,27 +4,27 @@ set -e
|
||||
# Software versions to install
|
||||
|
||||
_7ZIP_VERSION=2501
|
||||
BINUTILS_VERSION=2_45
|
||||
CLANG_VERSION=21.1.5
|
||||
CMAKE_VERSION=4.1.2
|
||||
BINUTILS_VERSION=2_45_1
|
||||
CLANG_VERSION=21.1.8
|
||||
CMAKE_VERSION=4.2.1
|
||||
FREEBSD_VERSION=12.4
|
||||
GCC_VERSION=15.2.0
|
||||
GLIBC_VERSION=2.42
|
||||
LINUX_HEADERS_VERSION=6.17.7
|
||||
MACOSX_SDK_VERSION=26.0
|
||||
OSXCROSS_VERSION=7e8a4d170cc6bda1f0a32f5dc5f6ace4676baf98
|
||||
LINUX_HEADERS_VERSION=6.18.1
|
||||
MACOSX_SDK_VERSION=26.1
|
||||
OSXCROSS_VERSION=2bc739ebe45db5d72e176d2a4e1c7dd95464e8e2
|
||||
MAKE_VERSION=4.4.1
|
||||
MINGW_VERSION=13.0.0
|
||||
XZ_VERSION=5.8.1
|
||||
XZ_VERSION=5.8.2
|
||||
TAR_VERSION=1.35
|
||||
|
||||
_7ZIP_SHA256="4ca3b7c6f2f67866b92622818b58233dc70367be2f36b498eb0bdeaaa44b53f4"
|
||||
CMAKE_SHA256="773cc679c3a7395413bd096523f8e5d6c39f8718af4e12eb4e4195f72f35e4ab"
|
||||
CMAKE_SHA256="c059bff1e97a2b6b5b0c0872263627486345ad0ed083298cb21cff2eda883980"
|
||||
FREEBSD_AARCH64_SHA256="6c401819bfb93e810c9f9aa670a1e4685f924df5e7e0c9c6397dd6c16c954fa2"
|
||||
FREEBSD_X86_64_SHA256="581c7edacfd2fca2bdf5791f667402d22fccd8a5e184635e0cac075564d57aa8"
|
||||
GLIBC_SHA256="d1775e32e4628e64ef930f435b67bb63af7599acb6be2b335b9f19f16509f17f"
|
||||
HEADERS_SHA256="ddf2ea0d4439e1d57136be3623102af9458f601f5b1cb77e83246e88aea09d0e"
|
||||
MACOSX_SDK_SHA256="07ccaa2891454713c3a230dd87283f76124193309d9a7617ebee45354c9302d2"
|
||||
HEADERS_SHA256="d0a78bf3f0d12aaa10af3b5adcaed5bc767b5b78705e5ef885d5e930b72e25d5"
|
||||
MACOSX_SDK_SHA256="beee7212d265a6d2867d0236cc069314b38d5fb3486a6515734e76fa210c784c"
|
||||
MAKE_SHA256="dd16fb1d67bfab79a72f5e8390735c49e3e8e70b4945a15ab1f81ddb78658fb3"
|
||||
TAR_SHA256="4d62ff37342ec7aed748535323930c7cf94acf71c3591882b26a7ea50f3edc16"
|
||||
|
||||
@@ -227,7 +227,7 @@ cd /root
|
||||
|
||||
tar xvf $CMAKE_FILE
|
||||
cp $CMAKE_NAME/bin/* /usr/local/bin
|
||||
cp -r $CMAKE_NAME/share/cmake-4.1 /usr/local/share
|
||||
cp -r $CMAKE_NAME/share/cmake-4.2 /usr/local/share
|
||||
|
||||
echo "Install clang"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
grep 'ERROR ' p2pool.log | grep -E -v 'submit_block|failed to bind|ZMQ is not running|block header for seed' > errors.log
|
||||
grep 'ERROR ' p2pool.log | grep -E -v 'submit_block|failed to bind|ZMQ is not running|block header for seed|ZMQReader|ZMQ reader|uv_poll_start returned error EBADF' > errors.log
|
||||
|
||||
if [ -s errors.log ]; then
|
||||
cat errors.log
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
//
|
||||
// Fixed difficulty for miners that connect to your node must be set in their config.json
|
||||
//
|
||||
// Note: nano sidechain uses
|
||||
// "block_time": 30
|
||||
// "uncle_penalty": 10
|
||||
{
|
||||
"name": "default",
|
||||
"password": "",
|
||||
|
||||
+7
-6
@@ -20,6 +20,7 @@
|
||||
#include "pool_block.h"
|
||||
#include "p2p_server.h"
|
||||
#include "side_chain.h"
|
||||
#include "params.h"
|
||||
|
||||
LOG_CATEGORY(BlockCache)
|
||||
|
||||
@@ -34,9 +35,9 @@ struct BlockCache::Impl : public nocopy_nomove
|
||||
{
|
||||
#if defined(__linux__) || defined(__unix__) || defined(_POSIX_VERSION) || defined(__MACH__)
|
||||
|
||||
Impl()
|
||||
explicit Impl(const Params& params)
|
||||
{
|
||||
const std::string cache_path = DATA_DIR + cache_name;
|
||||
const std::string cache_path = params.m_dataDir + cache_name;
|
||||
|
||||
m_fd = open(cache_path.c_str(), O_RDWR | O_CREAT, static_cast<mode_t>(0600));
|
||||
if (m_fd == -1) {
|
||||
@@ -88,8 +89,8 @@ struct BlockCache::Impl : public nocopy_nomove
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
Impl()
|
||||
: m_cachePath(DATA_DIR + cache_name)
|
||||
explicit Impl(const Params& params)
|
||||
: m_cachePath(params.m_dataDir + cache_name)
|
||||
, m_file(CreateFile(m_cachePath.c_str(), GENERIC_ALL, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_HIDDEN, NULL))
|
||||
, m_map(0)
|
||||
{
|
||||
@@ -157,8 +158,8 @@ struct BlockCache::Impl : public nocopy_nomove
|
||||
uint8_t* m_data = nullptr;
|
||||
};
|
||||
|
||||
BlockCache::BlockCache()
|
||||
: m_impl(new Impl())
|
||||
BlockCache::BlockCache(const Params& params)
|
||||
: m_impl(new Impl(params))
|
||||
, m_flushRunning(0)
|
||||
, m_storeIndex(0)
|
||||
, m_loadingStarted(0)
|
||||
|
||||
+2
-1
@@ -22,11 +22,12 @@ namespace p2pool {
|
||||
struct PoolBlock;
|
||||
class SideChain;
|
||||
class P2PServer;
|
||||
struct Params;
|
||||
|
||||
class BlockCache : public nocopy_nomove
|
||||
{
|
||||
public:
|
||||
BlockCache();
|
||||
explicit BlockCache(const Params& params);
|
||||
~BlockCache();
|
||||
|
||||
void store(const PoolBlock& block);
|
||||
|
||||
@@ -204,7 +204,7 @@ void BlockTemplate::shuffle_tx_order()
|
||||
}
|
||||
}
|
||||
|
||||
void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const Params* params)
|
||||
void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const Params& params)
|
||||
{
|
||||
if (data.major_version > HARDFORK_SUPPORTED_VERSION) {
|
||||
LOGERR(1, "got hardfork version " << data.major_version << ", expected <= " << HARDFORK_SUPPORTED_VERSION);
|
||||
@@ -269,7 +269,7 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const
|
||||
|
||||
m_blockHeaderSize = m_blockHeader.size();
|
||||
|
||||
m_poolBlockTemplate->m_minerWallet = params->m_miningWallet;
|
||||
m_poolBlockTemplate->m_minerWallet = params.m_miningWallet;
|
||||
|
||||
if (!m_sidechain->fill_sidechain_data(*m_poolBlockTemplate, m_shares)) {
|
||||
use_old_template();
|
||||
@@ -595,7 +595,7 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const
|
||||
m_poolBlockTemplate->m_transactions.push_back(m_mempoolTxs[m_mempoolTxsOrder[i]].id);
|
||||
}
|
||||
|
||||
m_poolBlockTemplate->m_minerWallet = params->m_miningWallet;
|
||||
m_poolBlockTemplate->m_minerWallet = params.m_miningWallet;
|
||||
|
||||
// Layout: [software id, version, random number, sidechain extra_nonce]
|
||||
uint32_t* sidechain_extra = m_poolBlockTemplate->m_sidechainExtraBuf;
|
||||
@@ -630,16 +630,16 @@ void BlockTemplate::update(const MinerData& data, const Mempool& mempool, const
|
||||
m_poolBlockTemplate->m_mergeMiningExtra.emplace(c.unique_id, std::move(v));
|
||||
}
|
||||
|
||||
if (params->m_subaddress.valid()) {
|
||||
if (params.m_subaddress.valid()) {
|
||||
uint8_t buf[HASH_SIZE + 2] = {};
|
||||
memcpy(buf, params->m_subaddress.view_public_key().h, HASH_SIZE);
|
||||
memcpy(buf, params.m_subaddress.view_public_key().h, HASH_SIZE);
|
||||
|
||||
m_poolBlockTemplate->m_mergeMiningExtra.emplace(keccak_subaddress_viewpub, std::vector(buf, buf + sizeof(buf)));
|
||||
}
|
||||
|
||||
if (!params->m_onionPubkey.empty()) {
|
||||
if (!params.m_onionPubkey.empty()) {
|
||||
uint8_t buf[HASH_SIZE + 2] = {};
|
||||
memcpy(buf, params->m_onionPubkey.h, HASH_SIZE);
|
||||
memcpy(buf, params.m_onionPubkey.h, HASH_SIZE);
|
||||
|
||||
m_poolBlockTemplate->m_mergeMiningExtra.emplace(keccak_onion_address_v3, std::vector(buf, buf + sizeof(buf)));
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
BlockTemplate(const BlockTemplate& b);
|
||||
BlockTemplate& operator=(const BlockTemplate& b);
|
||||
|
||||
void update(const MinerData& data, const Mempool& mempool, const Params* params);
|
||||
void update(const MinerData& data, const Mempool& mempool, const Params& params);
|
||||
uint64_t last_updated() const { return m_lastUpdated.load(); }
|
||||
|
||||
bool get_difficulties(const uint32_t template_id, uint64_t& height, uint64_t& sidechain_height, difficulty_type& mainchain_difficulty, difficulty_type& aux_diff, difficulty_type& sidechain_difficulty) const;
|
||||
|
||||
+13
-5
@@ -18,6 +18,7 @@
|
||||
#include "common.h"
|
||||
#include "uv_util.h"
|
||||
#include "wallet.h"
|
||||
#include "params.h"
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
@@ -118,7 +119,7 @@ public:
|
||||
BUF_SIZE = SLOT_SIZE * 8192,
|
||||
};
|
||||
|
||||
FORCEINLINE Worker()
|
||||
FORCEINLINE explicit Worker(const Params& p)
|
||||
: m_writePos(0)
|
||||
, m_readPos(0)
|
||||
, m_stopped(false)
|
||||
@@ -132,7 +133,7 @@ public:
|
||||
|
||||
std::setlocale(LC_ALL, "en_001");
|
||||
|
||||
m_logFilePath = DATA_DIR + log_file_name;
|
||||
m_logFilePath = p.m_logFilePath.empty() ? (p.m_dataDir + log_file_name) : p.m_logFilePath;
|
||||
|
||||
m_buf.resize(BUF_SIZE);
|
||||
|
||||
@@ -478,16 +479,23 @@ NOINLINE Writer::~Writer()
|
||||
m_buf[2] = static_cast<char>(static_cast<uint8_t>(size >> 8));
|
||||
m_buf[m_pos] = '\n';
|
||||
#ifndef P2POOL_LOG_DISABLE
|
||||
worker->write(m_buf, size);
|
||||
if (worker) {
|
||||
worker->write(m_buf, size);
|
||||
}
|
||||
else {
|
||||
fwrite(m_buf + 3, 1, size - 3, (m_buf[0] == 1) ? stdout : stderr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void start()
|
||||
void start(const Params& p)
|
||||
{
|
||||
#ifndef P2POOL_LOG_DISABLE
|
||||
worker = new Worker();
|
||||
worker = new Worker(p);
|
||||
|
||||
LOGINFO(0, "started");
|
||||
#else
|
||||
(void)p;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
namespace p2pool {
|
||||
|
||||
class Wallet;
|
||||
struct Params;
|
||||
|
||||
namespace log {
|
||||
|
||||
@@ -622,7 +623,7 @@ struct DummyStream
|
||||
|
||||
#endif
|
||||
|
||||
void start();
|
||||
void start(const Params& p);
|
||||
void reopen();
|
||||
void stop();
|
||||
|
||||
|
||||
+80
-51
@@ -38,7 +38,6 @@
|
||||
#endif // WITH_GRPC
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
#ifdef WITH_RANDOMX
|
||||
#include "randomx.h"
|
||||
@@ -72,6 +71,7 @@ void p2pool_usage()
|
||||
"--light-mode Don't allocate RandomX dataset, saves 2GB of RAM\n"
|
||||
"--loglevel Verbosity of the log, integer number between 0 and %d\n"
|
||||
"--data-dir Path to store general p2pool files (log, cache, peer data, etc.), default is current directory\n"
|
||||
"--log-file Path to the log file, default is \"p2pool.log\" in p2pool's working directory\n"
|
||||
"--sidechain-config Name of the p2pool sidechain parameters file (only use it if you run your own sidechain)\n"
|
||||
"--data-api Path to the p2pool JSON data (use it in tandem with an external web-server). Not affected by --data-dir setting!\n"
|
||||
"--local-api Enable /local/ path in api path for Stratum Server and built-in miner statistics\n"
|
||||
@@ -108,6 +108,7 @@ void p2pool_usage()
|
||||
"--full-validation Enables full share validation / increases CPU usage\n"
|
||||
"--onion-address Tell other peers to use this .onion address to connect to this node through TOR\n"
|
||||
"--no-clearnet-p2p Forces P2P server to listen on 127.0.0.1 and to not connect to clearnet IPs\n"
|
||||
"--params-file File name to load parameters from. It can't be used together with any other command line parameters\n"
|
||||
"--help Show this help message\n\n"
|
||||
"Example command line:\n\n"
|
||||
"%s --host 127.0.0.1 --rpc-port 18081 --zmq-port 18083 --wallet YOUR_WALLET_ADDRESS --stratum 0.0.0.0:%d --p2p 0.0.0.0:%d\n\n",
|
||||
@@ -222,6 +223,56 @@ int p2pool_test()
|
||||
return 0;
|
||||
}
|
||||
|
||||
static p2pool::Params get_params(int argc, const char* const argv[]) noexcept
|
||||
{
|
||||
try {
|
||||
std::vector<std::vector<std::string>> args;
|
||||
args.reserve(argc);
|
||||
|
||||
// Group command-line parameters by the pattern "--name [data1 data2 ... data_n]"
|
||||
// Each parameter starting with "--" can have 0 or more values attached to it
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
std::string_view arg = argv[i];
|
||||
|
||||
if ((arg.size() > 2) && (arg[0] == '-') && (arg[1] == '-')) {
|
||||
// Store the parameter name without the "--" prefix
|
||||
arg.remove_prefix(2);
|
||||
args.emplace_back(1, std::string(arg));
|
||||
}
|
||||
else if (!args.empty()) {
|
||||
args.back().emplace_back(std::move(arg));
|
||||
}
|
||||
}
|
||||
|
||||
p2pool::Params params(args);
|
||||
|
||||
if (params.valid()) {
|
||||
return params;
|
||||
}
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
}
|
||||
|
||||
printf("Invalid or missing command line. Try \"p2pool --help\".\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
static p2pool::Params get_params(const std::string& params_file) noexcept
|
||||
{
|
||||
try {
|
||||
p2pool::Params params(p2pool::parse_config(params_file));
|
||||
|
||||
if (params.valid()) {
|
||||
return params;
|
||||
}
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
}
|
||||
|
||||
printf("Invalid or missing command line. Try \"p2pool --help\".\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (argc == 1) {
|
||||
@@ -229,11 +280,10 @@ int main(int argc, char* argv[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool is_mini = false;
|
||||
bool is_nano = false;
|
||||
std::string params_file;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "/help") || !strcmp(argv[i], "-h") || !strcmp(argv[i], "/h")) {
|
||||
if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "/help") || !strcmp(argv[i], "-h") || !strcmp(argv[i], "/h") || !strcmp(argv[i], "/?")) {
|
||||
p2pool_usage();
|
||||
return 0;
|
||||
}
|
||||
@@ -247,52 +297,14 @@ int main(int argc, char* argv[])
|
||||
return p2pool_test();
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--data-dir") == 0) && (i + 1 < argc)) {
|
||||
std::string path = argv[++i];
|
||||
p2pool::DATA_DIR = std::move(path);
|
||||
p2pool::fixup_path(p2pool::DATA_DIR);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[i], "--mini")) is_mini = true;
|
||||
if (!strcmp(argv[i], "--nano")) is_nano = true;
|
||||
}
|
||||
|
||||
// If the data directory is not set, check if P2Pool has write access to the current directory
|
||||
// If it doesn't, switch to user's home directory
|
||||
if (p2pool::DATA_DIR.empty()) {
|
||||
std::ofstream f("p2pool.tmp");
|
||||
if (f && f.put(' ')) {
|
||||
f.close();
|
||||
std::remove("p2pool.tmp");
|
||||
}
|
||||
else {
|
||||
char buf[1024];
|
||||
size_t size = sizeof(buf);
|
||||
|
||||
if (uv_os_homedir(buf, &size) == 0) {
|
||||
p2pool::DATA_DIR.assign(buf, size);
|
||||
p2pool::fixup_path(p2pool::DATA_DIR);
|
||||
|
||||
p2pool::DATA_DIR += ".p2pool/";
|
||||
|
||||
if (is_mini) {
|
||||
p2pool::DATA_DIR += "mini/";
|
||||
}
|
||||
else if (is_nano) {
|
||||
p2pool::DATA_DIR += "nano/";
|
||||
}
|
||||
}
|
||||
if (!strcmp(argv[i], "--params-file") && (i + 1 < argc)) {
|
||||
params_file = argv[++i];
|
||||
}
|
||||
}
|
||||
|
||||
if (!p2pool::DATA_DIR.empty()) {
|
||||
printf("Using \"%s\" for P2Pool files\n", p2pool::DATA_DIR.c_str());
|
||||
}
|
||||
|
||||
// Try to create it if it doesn't exist
|
||||
if (!p2pool::DATA_DIR.empty()) {
|
||||
std::error_code err;
|
||||
std::filesystem::create_directories(p2pool::DATA_DIR, err);
|
||||
if (!params_file.empty() && (argc != 3)) {
|
||||
fprintf(stderr, "--params-file can't be combined with other command line parameters\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if defined(_WIN32) && defined(_MSC_VER) && !defined(NDEBUG)
|
||||
@@ -303,14 +315,29 @@ int main(int argc, char* argv[])
|
||||
|
||||
memory_tracking_start();
|
||||
|
||||
// Create default loop here
|
||||
int result;
|
||||
{
|
||||
|
||||
// Create the default libuv loop and initialize libuv here
|
||||
// It will call the important stuff like WSAStartup and many other things
|
||||
// Some P2Pool code will not work without libuv initialized, so the code above this line must be minimal
|
||||
uv_default_loop();
|
||||
|
||||
p2pool::log::start();
|
||||
const p2pool::Params params = params_file.empty() ? get_params(argc, argv) : get_params(params_file);
|
||||
|
||||
if (!params.m_dataDir.empty()) {
|
||||
printf("Using \"%s\" for P2Pool files\n", params.m_dataDir.c_str());
|
||||
|
||||
// Try to create it if it doesn't exist
|
||||
std::error_code err;
|
||||
std::filesystem::create_directories(params.m_dataDir, err);
|
||||
}
|
||||
|
||||
p2pool::log::start(params);
|
||||
|
||||
p2pool::init_crypto_cache();
|
||||
|
||||
int result = static_cast<int>(curl_global_init_mem(CURL_GLOBAL_ALL, p2pool::malloc_hook, p2pool::free_hook, p2pool::realloc_hook, p2pool::strdup_hook, p2pool::calloc_hook));
|
||||
result = static_cast<int>(curl_global_init_mem(CURL_GLOBAL_ALL, p2pool::malloc_hook, p2pool::free_hook, p2pool::realloc_hook, p2pool::strdup_hook, p2pool::calloc_hook));
|
||||
if (result != CURLE_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -327,7 +354,7 @@ int main(int argc, char* argv[])
|
||||
#endif
|
||||
|
||||
try {
|
||||
p2pool::p2pool pool(argc, argv);
|
||||
p2pool::p2pool pool(params);
|
||||
result = pool.run();
|
||||
}
|
||||
catch (...) {
|
||||
@@ -354,6 +381,8 @@ int main(int argc, char* argv[])
|
||||
uv_library_shutdown();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if (!memory_tracking_stop()) {
|
||||
result = 1;
|
||||
}
|
||||
|
||||
+13
-10
@@ -48,9 +48,9 @@ LOG_CATEGORY(P2PServer)
|
||||
|
||||
static constexpr char saved_peer_list_file_name[] = "p2pool_peers.txt";
|
||||
static constexpr char saved_onion_peer_list_file_name[] = "p2pool_onion_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 const char* seed_nodes[] = { "seeds.p2pool.io", "main.p2poolpeers.net", "" };
|
||||
static const char* seed_nodes_mini[] = { "seeds-mini.p2pool.io", "mini.p2poolpeers.net", "" };
|
||||
static const char* seed_nodes_nano[] = { "seeds-nano.p2pool.io", "nano.p2poolpeers.net", ""};
|
||||
|
||||
static constexpr int DEFAULT_BACKLOG = 16;
|
||||
static constexpr uint64_t DEFAULT_BAN_TIME = 600;
|
||||
@@ -66,7 +66,7 @@ static constexpr hash seed_onion_nodes[] = {
|
||||
P2PServer::P2PServer(p2pool* pool)
|
||||
: TCPServer(DEFAULT_BACKLOG, P2PClient::allocate, pool->params().m_socks5Proxy)
|
||||
, m_pool(pool)
|
||||
, m_cache(pool->params().m_blockCache ? new BlockCache() : nullptr)
|
||||
, m_cache(pool->params().m_blockCache ? new BlockCache(pool->params()) : nullptr)
|
||||
, m_cacheLoaded(false)
|
||||
, m_initialPeerList(pool->params().m_p2pPeerList)
|
||||
, m_cachedBlocks(nullptr)
|
||||
@@ -561,7 +561,9 @@ void P2PServer::save_peer_list_async()
|
||||
|
||||
void P2PServer::save_peer_list()
|
||||
{
|
||||
const std::string path = DATA_DIR + saved_peer_list_file_name;
|
||||
const Params& params = m_pool->params();
|
||||
|
||||
const std::string path = params.m_dataDir + saved_peer_list_file_name;
|
||||
|
||||
std::ofstream f(path, std::ios::binary);
|
||||
|
||||
@@ -606,7 +608,7 @@ void P2PServer::save_peer_list()
|
||||
const SideChain& s = m_pool->side_chain();
|
||||
|
||||
if (s.onion_pubkeys_count() > 0) {
|
||||
const std::string onion_path = DATA_DIR + saved_onion_peer_list_file_name;
|
||||
const std::string onion_path = params.m_dataDir + saved_onion_peer_list_file_name;
|
||||
|
||||
f.open(onion_path, std::ios::binary);
|
||||
|
||||
@@ -726,7 +728,7 @@ void P2PServer::load_peer_list()
|
||||
|
||||
// Finally load peers from p2pool_peers.txt and p2pool_onion_peers.txt
|
||||
for (size_t i = 0, n = (m_socks5Proxy.empty() ? 1 : 2); i < n; ++i) {
|
||||
const std::string path = DATA_DIR + (i ? saved_onion_peer_list_file_name : saved_peer_list_file_name);
|
||||
const std::string path = m_pool->params().m_dataDir + (i ? saved_onion_peer_list_file_name : saved_peer_list_file_name);
|
||||
|
||||
std::ifstream f(path);
|
||||
|
||||
@@ -1295,11 +1297,12 @@ void P2PServer::on_timer()
|
||||
return;
|
||||
}
|
||||
|
||||
++m_timerCounter;
|
||||
const uint64_t t = ++m_timerCounter;
|
||||
|
||||
if (!m_initialPeerList.empty()) {
|
||||
if ((t == 1) && !m_initialPeerList.empty()) {
|
||||
connect_to_peers(m_initialPeerList);
|
||||
m_initialPeerList.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
flush_cache();
|
||||
@@ -1892,7 +1895,7 @@ void P2PServer::P2PClient::reset()
|
||||
if (server->m_fastestPeer == this) {
|
||||
server->m_fastestPeer = nullptr;
|
||||
}
|
||||
if (m_addressType == AddressType::DomainName) {
|
||||
if ((m_addressType == AddressType::DomainName) && m_connectedTime) {
|
||||
--server->m_numOnionConnections;
|
||||
}
|
||||
}
|
||||
|
||||
+46
-79
@@ -63,8 +63,9 @@ namespace p2pool {
|
||||
|
||||
static uint64_t BLOCK_HEADERS_REQUIRED = 720;
|
||||
|
||||
p2pool::p2pool(int argc, char* argv[])
|
||||
p2pool::p2pool(const Params& params)
|
||||
: m_stopped(false)
|
||||
, m_params(params)
|
||||
, m_updateSeed(true)
|
||||
, m_submitBlockData{}
|
||||
, m_zmqLastActive(0)
|
||||
@@ -73,49 +74,33 @@ p2pool::p2pool(int argc, char* argv[])
|
||||
{
|
||||
LOGINFO(1, log::LightCyan() << VERSION);
|
||||
|
||||
Params* p = new Params(argc, argv);
|
||||
|
||||
if (!p->valid()) {
|
||||
LOGERR(1, "Invalid or missing command line. Try \"p2pool --help\".");
|
||||
delete p;
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
m_params = p;
|
||||
|
||||
// P2Pool-nano requires more Monero blocks for the initial sync
|
||||
if (m_params->m_nano) {
|
||||
if (m_params.m_nano) {
|
||||
BLOCK_HEADERS_REQUIRED = 1440;
|
||||
}
|
||||
|
||||
bkg_jobs_tracker = new BackgroundJobTracker();
|
||||
|
||||
#ifdef WITH_UPNP
|
||||
if (p->m_upnp) {
|
||||
if (m_params.m_upnp) {
|
||||
init_upnp();
|
||||
}
|
||||
#endif
|
||||
|
||||
for (Params::Host& h : p->m_hosts) {
|
||||
if (!h.init_display_name(*p)) {
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
|
||||
m_currentHostIndex = 0;
|
||||
|
||||
m_hostPing.resize(p->m_hosts.size());
|
||||
m_hostPing.resize(m_params.m_hosts.size());
|
||||
|
||||
hash pub, sec, eph_public_key;
|
||||
generate_keys(pub, sec);
|
||||
|
||||
uint8_t view_tag;
|
||||
if (!p->m_miningWallet.get_eph_public_key(sec, 0, eph_public_key, view_tag)) {
|
||||
if (!m_params.m_miningWallet.get_eph_public_key(sec, 0, eph_public_key, view_tag)) {
|
||||
LOGERR(1, "Invalid wallet address: get_eph_public_key failed");
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
const NetworkType type = p->m_miningWallet.type();
|
||||
const NetworkType type = m_params.m_miningWallet.type();
|
||||
|
||||
if (type == NetworkType::Testnet) {
|
||||
LOGWARN(1, "Mining to a testnet wallet address");
|
||||
@@ -196,34 +181,17 @@ p2pool::p2pool(int argc, char* argv[])
|
||||
}
|
||||
m_timer.data = this;
|
||||
|
||||
m_api = p->m_apiPath.empty() ? nullptr : new p2pool_api(p->m_apiPath, p->m_localStats);
|
||||
m_api = m_params.m_apiPath.empty() ? nullptr : new p2pool_api(m_params.m_apiPath, m_params.m_localStats);
|
||||
|
||||
if (p->m_localStats && !m_api) {
|
||||
if (m_params.m_localStats && !m_api) {
|
||||
LOGERR(1, "--local-api and --stratum-api command line parameters can't be used without --data-api");
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
m_sideChain = new SideChain(this, type, p->m_mini ? "mini" : (p->m_nano ? "nano" : nullptr));
|
||||
|
||||
const int p2p_port = m_sideChain->is_mini() ? DEFAULT_P2P_PORT_MINI : (m_sideChain->is_nano() ? DEFAULT_P2P_PORT_NANO : DEFAULT_P2P_PORT);
|
||||
|
||||
if (p->m_noClearnetP2P) {
|
||||
char buf[48] = {};
|
||||
log::Stream s(buf);
|
||||
s << "127.0.0.1:" << p2p_port;
|
||||
|
||||
p->m_p2pAddresses = buf;
|
||||
}
|
||||
else if (p->m_p2pAddresses.empty()) {
|
||||
char buf[48] = {};
|
||||
log::Stream s(buf);
|
||||
s << "[::]:" << p2p_port << ",0.0.0.0:" << p2p_port;
|
||||
|
||||
p->m_p2pAddresses = buf;
|
||||
}
|
||||
m_sideChain = new SideChain(this, type, m_params.m_mini ? "mini" : (m_params.m_nano ? "nano" : nullptr));
|
||||
|
||||
#ifdef WITH_RANDOMX
|
||||
if (p->m_disableRandomX) {
|
||||
if (m_params.m_disableRandomX) {
|
||||
m_hasher = new RandomX_Hasher_RPC(this);
|
||||
}
|
||||
else {
|
||||
@@ -252,7 +220,7 @@ p2pool::p2pool(int argc, char* argv[])
|
||||
p2pool::~p2pool()
|
||||
{
|
||||
#ifdef WITH_UPNP
|
||||
if (m_params->m_upnp) {
|
||||
if (m_params.m_upnp) {
|
||||
destroy_upnp();
|
||||
}
|
||||
#endif
|
||||
@@ -295,7 +263,6 @@ p2pool::~p2pool()
|
||||
delete m_hasher;
|
||||
delete m_blockTemplate;
|
||||
delete m_mempool;
|
||||
delete m_params;
|
||||
|
||||
{
|
||||
auto* p = bkg_jobs_tracker;
|
||||
@@ -318,7 +285,7 @@ void p2pool::update_host_ping(const std::string& display_name, double ping)
|
||||
LOGWARN(1, display_name << " ping is " << ping << " ms, this is too high for an efficient mining. Try to use a different node, or your own local node.");
|
||||
}
|
||||
|
||||
const std::vector<Params::Host>& v = m_params->m_hosts;
|
||||
const std::vector<Params::Host>& v = m_params.m_hosts;
|
||||
|
||||
for (size_t i = 0, n = v.size(); i < n; ++i) {
|
||||
if (v[i].m_displayName == display_name) {
|
||||
@@ -332,8 +299,8 @@ void p2pool::print_hosts() const
|
||||
{
|
||||
const Params::Host& host = current_host();
|
||||
|
||||
for (size_t i = 0, n = m_params->m_hosts.size(); i < n; ++i) {
|
||||
const Params::Host& h = m_params->m_hosts[i];
|
||||
for (size_t i = 0, n = m_params.m_hosts.size(); i < n; ++i) {
|
||||
const Params::Host& h = m_params.m_hosts[i];
|
||||
|
||||
char buf[64] = {};
|
||||
if (m_hostPing[i] > 0.0) {
|
||||
@@ -417,7 +384,7 @@ void p2pool::handle_tx(TxMempoolData& tx)
|
||||
}
|
||||
|
||||
#if TEST_MEMPOOL_PICKING_ALGORITHM
|
||||
m_blockTemplate->update(miner_data(), *m_mempool, &m_params->m_wallet);
|
||||
m_blockTemplate->update(miner_data(), *m_mempool, &m_params.m_wallet);
|
||||
#endif
|
||||
|
||||
m_zmqLastActive = seconds_since_epoch();
|
||||
@@ -557,7 +524,7 @@ void p2pool::get_missing_heights()
|
||||
|
||||
const Params::Host& host = current_host();
|
||||
|
||||
JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
[this, h](const char* data, size_t size, double)
|
||||
{
|
||||
ChainMain block;
|
||||
@@ -801,14 +768,14 @@ void p2pool::update_aux_data(const hash& chain_id)
|
||||
void p2pool::send_aux_job_donation()
|
||||
{
|
||||
#ifdef WITH_TLS
|
||||
if (m_params->m_authorKeyFile.empty()) {
|
||||
if (m_params.m_authorKeyFile.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::ifstream f(m_params->m_authorKeyFile, std::ios::binary | std::ios::ate);
|
||||
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);
|
||||
LOGERR(1, "send_aux_job_donation: failed to open " << m_params.m_authorKeyFile);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -816,7 +783,7 @@ void p2pool::send_aux_job_donation()
|
||||
ON_SCOPE_LEAVE([&key](){ secure_zero_memory(key); });
|
||||
|
||||
if (f.tellg() != static_cast<std::streampos>(sizeof(key))) {
|
||||
LOGERR(1, "send_aux_job_donation: " << m_params->m_authorKeyFile << " has an invalid size");
|
||||
LOGERR(1, "send_aux_job_donation: " << m_params.m_authorKeyFile << " has an invalid size");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -824,21 +791,21 @@ void p2pool::send_aux_job_donation()
|
||||
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);
|
||||
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");
|
||||
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");
|
||||
LOGERR(1, "send_aux_job_donation: " << m_params.m_authorKeyFile << ": signature verification failed");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1162,7 +1129,7 @@ void p2pool::submit_block() const
|
||||
|
||||
const uint64_t t1 = microseconds_since_epoch();
|
||||
|
||||
JSONRPCRequest::call(host.m_address, host.m_rpcPort, request, host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
JSONRPCRequest::call(host.m_address, host.m_rpcPort, request, host.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
[height, diff, template_id, nonce, extra_nonce, merge_mining_root, is_external](const char* data, size_t size, double)
|
||||
{
|
||||
rapidjson::Document doc;
|
||||
@@ -1281,7 +1248,7 @@ void p2pool::download_block_headers1(uint64_t current_height)
|
||||
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,
|
||||
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)) {
|
||||
@@ -1314,7 +1281,7 @@ void p2pool::download_block_headers2(uint64_t current_height)
|
||||
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,
|
||||
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)) {
|
||||
@@ -1350,7 +1317,7 @@ void p2pool::download_block_headers3(uint64_t start_height, uint64_t current_hei
|
||||
s.m_pos = 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,
|
||||
JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
[this, start_height, next_height, 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);
|
||||
@@ -1383,7 +1350,7 @@ void p2pool::download_block_headers4(uint64_t start_height, uint64_t current_hei
|
||||
s.m_pos = 0;
|
||||
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_block_headers_range\",\"params\":{\"start_height\":" << start_height << ",\"end_height\":" << current_height - 1 << "}}" << '\0';
|
||||
|
||||
JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
JSONRPCRequest::call(host.m_address, host.m_rpcPort, buf, host.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
[this, start_height, current_height, host](const char* data, size_t size, double)
|
||||
{
|
||||
if (parse_block_headers_range(data, size) == current_height - start_height) {
|
||||
@@ -1392,14 +1359,14 @@ void p2pool::download_block_headers4(uint64_t start_height, uint64_t current_hei
|
||||
m_p2pServer = new P2PServer(this);
|
||||
m_stratumServer = new StratumServer(this);
|
||||
#if defined(WITH_RANDOMX) && !defined(P2POOL_UNIT_TESTS)
|
||||
if (m_params->m_minerThreads) {
|
||||
start_mining(m_params->m_minerThreads);
|
||||
if (m_params.m_minerThreads) {
|
||||
start_mining(m_params.m_minerThreads);
|
||||
}
|
||||
{
|
||||
WriteLock lock(m_ZMQReaderLock);
|
||||
|
||||
try {
|
||||
m_ZMQReader = new ZMQReader(host.m_address, host.m_zmqPort, m_params->m_socks5Proxy, this);
|
||||
m_ZMQReader = new ZMQReader(host.m_address, host.m_zmqPort, m_params.m_socks5Proxy, this);
|
||||
m_zmqLastActive = seconds_since_epoch();
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
@@ -1413,10 +1380,10 @@ void p2pool::download_block_headers4(uint64_t start_height, uint64_t current_hei
|
||||
get_miner_data();
|
||||
|
||||
// Get ping times for all other hosts
|
||||
for (const Params::Host& h : m_params->m_hosts) {
|
||||
for (const Params::Host& h : m_params.m_hosts) {
|
||||
const std::string& name = h.m_displayName;
|
||||
if (name != host.m_displayName) {
|
||||
JSONRPCRequest::call(h.m_address, h.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_version\"}", h.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
JSONRPCRequest::call(h.m_address, h.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_version\"}", h.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
[this, name](const char*, size_t, double tcp_ping) { update_host_ping(name, tcp_ping); },
|
||||
[](const char*, size_t, double) {});
|
||||
}
|
||||
@@ -1424,7 +1391,7 @@ void p2pool::download_block_headers4(uint64_t start_height, uint64_t current_hei
|
||||
|
||||
std::vector<IMergeMiningClient*> merge_mining_clients;
|
||||
|
||||
for (const auto& h : m_params->m_mergeMiningHosts) {
|
||||
for (const auto& h : m_params.m_mergeMiningHosts) {
|
||||
IMergeMiningClient* c = IMergeMiningClient::create(this, h.m_host, h.m_wallet);
|
||||
if (c) {
|
||||
merge_mining_clients.push_back(c);
|
||||
@@ -1525,7 +1492,7 @@ void p2pool::get_info()
|
||||
{
|
||||
const Params::Host& host = current_host();
|
||||
|
||||
JSONRPCRequest::call(host.m_address, host.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_info\"}", host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
JSONRPCRequest::call(host.m_address, host.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_info\"}", host.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
[this](const char* data, size_t size, double)
|
||||
{
|
||||
parse_get_info_rpc(data, size);
|
||||
@@ -1549,7 +1516,7 @@ void p2pool::load_found_blocks()
|
||||
return;
|
||||
}
|
||||
|
||||
std::ifstream f(DATA_DIR + FOUND_BLOCKS_FILE);
|
||||
std::ifstream f(m_params.m_dataDir + FOUND_BLOCKS_FILE);
|
||||
if (!f.is_open()) {
|
||||
return;
|
||||
}
|
||||
@@ -1644,7 +1611,7 @@ void p2pool::get_version()
|
||||
{
|
||||
const Params::Host& host = current_host();
|
||||
|
||||
JSONRPCRequest::call(host.m_address, host.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_version\"}", host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
JSONRPCRequest::call(host.m_address, host.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_version\"}", host.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
[this](const char* data, size_t size, double)
|
||||
{
|
||||
parse_get_version_rpc(data, size);
|
||||
@@ -1721,7 +1688,7 @@ void p2pool::get_miner_data(bool retry)
|
||||
|
||||
const Params::Host& host = current_host();
|
||||
|
||||
JSONRPCRequest::call(host.m_address, host.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_miner_data\"}", host.m_rpcLogin, m_params->m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
JSONRPCRequest::call(host.m_address, host.m_rpcPort, "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_miner_data\"}", host.m_rpcLogin, m_params.m_socks5Proxy, host.m_rpcSSL, host.m_rpcSSL_Fingerprint,
|
||||
[this, host](const char* data, size_t size, double tcp_ping)
|
||||
{
|
||||
parse_get_miner_data_rpc(data, size);
|
||||
@@ -2085,7 +2052,7 @@ void p2pool::api_update_block_found(const ChainMain* data, const PoolBlock* bloc
|
||||
difficulty_type diff;
|
||||
|
||||
if (data && get_difficulty_at_height(data->height, diff)) {
|
||||
const std::string path = DATA_DIR + FOUND_BLOCKS_FILE;
|
||||
const std::string path = m_params.m_dataDir + FOUND_BLOCKS_FILE;
|
||||
std::ofstream f(path, std::ios::app);
|
||||
if (f.is_open()) {
|
||||
f << cur_time << ' ' << data->height << ' ' << data->id << ' ' << diff << ' ' << total_hashes << '\n';
|
||||
@@ -2141,7 +2108,7 @@ void p2pool::on_external_block(const PoolBlock& block)
|
||||
|
||||
void p2pool::api_update_aux_data()
|
||||
{
|
||||
if (!m_api || !m_params->m_localStats || m_stopped) {
|
||||
if (!m_api || !m_params.m_localStats || m_stopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2291,7 +2258,7 @@ bool p2pool::zmq_running() const
|
||||
|
||||
const Params::Host& p2pool::switch_host()
|
||||
{
|
||||
const std::vector<Params::Host>& v = m_params->m_hosts;
|
||||
const std::vector<Params::Host>& v = m_params.m_hosts;
|
||||
return v[++m_currentHostIndex % v.size()];
|
||||
}
|
||||
|
||||
@@ -2316,7 +2283,7 @@ void p2pool::reconnect_to_host()
|
||||
m_ZMQReader = nullptr;
|
||||
|
||||
try {
|
||||
ZMQReader* new_reader = new ZMQReader(new_host.m_address, new_host.m_zmqPort, m_params->m_socks5Proxy, this);
|
||||
ZMQReader* new_reader = new ZMQReader(new_host.m_address, new_host.m_zmqPort, m_params.m_socks5Proxy, this);
|
||||
m_zmqLastActive = seconds_since_epoch();
|
||||
m_ZMQReader = new_reader;
|
||||
}
|
||||
@@ -2332,7 +2299,7 @@ void p2pool::reconnect_to_host()
|
||||
|
||||
int p2pool::run()
|
||||
{
|
||||
if (!m_params->valid()) {
|
||||
if (!m_params.valid()) {
|
||||
LOGERR(1, "Invalid or missing command line. Try \"p2pool --help\".");
|
||||
return 1;
|
||||
}
|
||||
@@ -2343,8 +2310,8 @@ int p2pool::run()
|
||||
}
|
||||
|
||||
#ifdef WITH_TLS
|
||||
if (!m_params->m_tlsCert.empty() && !m_params->m_tlsCertKey.empty()) {
|
||||
if (!ServerTls::load_from_files(m_params->m_tlsCert.c_str(), m_params->m_tlsCertKey.c_str())) {
|
||||
if (!m_params.m_tlsCert.empty() && !m_params.m_tlsCertKey.empty()) {
|
||||
if (!ServerTls::load_from_files(m_params.m_tlsCert.c_str(), m_params.m_tlsCertKey.c_str())) {
|
||||
LOGERR(1, "Failed to load TLS files");
|
||||
return 1;
|
||||
}
|
||||
|
||||
+4
-4
@@ -40,7 +40,7 @@ struct PoolBlock;
|
||||
class p2pool : public MinerCallbackHandler, public nocopy_nomove
|
||||
{
|
||||
public:
|
||||
p2pool(int argc, char* argv[]);
|
||||
explicit p2pool(const Params& params);
|
||||
~p2pool() override;
|
||||
|
||||
int run();
|
||||
@@ -48,13 +48,13 @@ public:
|
||||
bool stopped() const { return m_stopped; }
|
||||
void stop();
|
||||
|
||||
const Params& params() const { return *m_params; }
|
||||
const Params& params() const { return m_params; }
|
||||
BlockTemplate& block_template() { return *m_blockTemplate; }
|
||||
SideChain& side_chain() { return *m_sideChain; }
|
||||
|
||||
FORCEINLINE const Params::Host& current_host() const
|
||||
{
|
||||
const std::vector<Params::Host>& v = m_params->m_hosts;
|
||||
const std::vector<Params::Host>& v = m_params.m_hosts;
|
||||
return v[m_currentHostIndex % v.size()];
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ private:
|
||||
|
||||
std::atomic<bool> m_stopped;
|
||||
|
||||
const Params* m_params;
|
||||
const Params& m_params;
|
||||
std::vector<double> m_hostPing;
|
||||
|
||||
std::atomic<uint32_t> m_currentHostIndex;
|
||||
|
||||
+136
-73
@@ -19,6 +19,7 @@
|
||||
#include "params.h"
|
||||
#include "stratum_server.h"
|
||||
#include "p2p_server.h"
|
||||
#include <fstream>
|
||||
|
||||
LOG_CATEGORY(Params)
|
||||
|
||||
@@ -29,13 +30,21 @@ namespace p2pool {
|
||||
static constexpr uint64_t MIN_STRATUM_BAN_TIME = UINT64_C(1);
|
||||
static constexpr uint64_t MAX_STRATUM_BAN_TIME = (UINT64_C(1) << 34) - 1;
|
||||
|
||||
Params::Params(int argc, char* const argv[])
|
||||
Params::Params(const std::vector<std::vector<std::string>>& args)
|
||||
{
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
auto has1 = [](const auto& v) { return (v.size() > 1) && !v[1].empty();};
|
||||
auto has2 = [](const auto& v) { return (v.size() > 2) && !v[2].empty();};
|
||||
|
||||
for (const auto& arg : args) {
|
||||
// Ignore empty parameters
|
||||
if (arg.empty() || arg[0].empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
|
||||
if ((strcmp(argv[i], "--host") == 0) && (i + 1 < argc)) {
|
||||
const char* address = argv[++i];
|
||||
if ((arg[0] == "host") && has1(arg)) {
|
||||
const char* address = arg[1].c_str();
|
||||
|
||||
if (m_hosts.empty()) {
|
||||
m_hosts.emplace_back();
|
||||
@@ -49,31 +58,31 @@ Params::Params(int argc, char* const argv[])
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--rpc-port") == 0) && (i + 1 < argc)) {
|
||||
if ((arg[0] == "rpc-port") && has1(arg)) {
|
||||
if (m_hosts.empty()) {
|
||||
m_hosts.emplace_back();
|
||||
}
|
||||
|
||||
m_hosts.back().m_rpcPort = static_cast<int32_t>(std::min(std::max(strtoul(argv[++i], nullptr, 10), 1UL), 65535UL));
|
||||
m_hosts.back().m_rpcPort = static_cast<int32_t>(std::min(std::max(strtoul(arg[1].c_str(), nullptr, 10), 1UL), 65535UL));
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--zmq-port") == 0) && (i + 1 < argc)) {
|
||||
if ((arg[0] == "zmq-port") && has1(arg)) {
|
||||
if (m_hosts.empty()) {
|
||||
m_hosts.emplace_back();
|
||||
}
|
||||
|
||||
m_hosts.back().m_zmqPort = static_cast<int32_t>(std::min(std::max(strtoul(argv[++i], nullptr, 10), 1UL), 65535UL));
|
||||
m_hosts.back().m_zmqPort = static_cast<int32_t>(std::min(std::max(strtoul(arg[1].c_str(), nullptr, 10), 1UL), 65535UL));
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "--light-mode") == 0) {
|
||||
if (arg[0] == "light-mode") {
|
||||
m_lightMode = true;
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--wallet") == 0) && (i + 1 < argc)) {
|
||||
const char* s = argv[++i];
|
||||
if ((arg[0] == "wallet") && has1(arg)) {
|
||||
const char* s = arg[1].c_str();
|
||||
|
||||
if (!m_mainWallet.decode(s)) {
|
||||
LOGERR(1, "Wallet " << s << " failed to decode");
|
||||
@@ -82,8 +91,8 @@ Params::Params(int argc, char* const argv[])
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--subaddress") == 0) && (i + 1 < argc)) {
|
||||
const char* s = argv[++i];
|
||||
if ((arg[0] == "subaddress") && has1(arg)) {
|
||||
const char* s = arg[1].c_str();
|
||||
|
||||
if (!m_subaddress.decode(s)) {
|
||||
LOGERR(1, "Subaddress " << s << " failed to decode");
|
||||
@@ -92,111 +101,115 @@ Params::Params(int argc, char* const argv[])
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--stratum") == 0) && (i + 1 < argc)) {
|
||||
m_stratumAddresses = argv[++i];
|
||||
if ((arg[0] == "stratum") && has1(arg)) {
|
||||
m_stratumAddresses = arg[1];
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--stratum-ban-time") == 0) && (i + 1 < argc)) {
|
||||
m_stratumBanTime = strtoull(argv[++i], nullptr, 10);
|
||||
if ((arg[0] == "stratum-ban-time") && has1(arg)) {
|
||||
m_stratumBanTime = strtoull(arg[1].c_str(), nullptr, 10);
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--p2p") == 0) && (i + 1 < argc)) {
|
||||
m_p2pAddresses = argv[++i];
|
||||
if ((arg[0] == "p2p") && has1(arg)) {
|
||||
m_p2pAddresses = arg[1];
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--addpeers") == 0) && (i + 1 < argc)) {
|
||||
m_p2pPeerList = argv[++i];
|
||||
if ((arg[0] == "addpeers") && has1(arg)) {
|
||||
m_p2pPeerList = arg[1];
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--loglevel") == 0) && (i + 1 < argc)) {
|
||||
const int level = std::min(std::max<int>(static_cast<int>(strtol(argv[++i], nullptr, 10)), 0), log::MAX_GLOBAL_LOG_LEVEL);
|
||||
if ((arg[0] == "loglevel") && has1(arg)) {
|
||||
const int level = std::min(std::max<int>(static_cast<int>(strtol(arg[1].c_str(), nullptr, 10)), 0), log::MAX_GLOBAL_LOG_LEVEL);
|
||||
log::GLOBAL_LOG_LEVEL = level;
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--data-dir") == 0) && (i + 1 < argc)) {
|
||||
// Processed in main.cpp
|
||||
++i;
|
||||
if ((arg[0] == "data-dir") && has1(arg)) {
|
||||
m_dataDir = arg[1];
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--sidechain-config") == 0) && (i + 1 < argc)) {
|
||||
m_sidechainConfig = argv[++i];
|
||||
if ((arg[0] == "log-file") && has1(arg)) {
|
||||
m_logFilePath = arg[1];
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--data-api") == 0) && (i + 1 < argc)) {
|
||||
m_apiPath = argv[++i];
|
||||
if ((arg[0] == "sidechain-config") && has1(arg)) {
|
||||
m_sidechainConfig = arg[1];
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--local-api") == 0) || (strcmp(argv[i], "--stratum-api") == 0)) {
|
||||
if ((arg[0] == "data-api") && has1(arg)) {
|
||||
m_apiPath = arg[1];
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((arg[0] == "local-api") || (arg[0] == "stratum-api")) {
|
||||
m_localStats = true;
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "--no-cache") == 0) {
|
||||
if (arg[0] == "no-cache") {
|
||||
m_blockCache = false;
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "--no-color") == 0) {
|
||||
if (arg[0] == "no-color") {
|
||||
log::CONSOLE_COLORS = false;
|
||||
ok = true;
|
||||
}
|
||||
|
||||
#ifdef WITH_RANDOMX
|
||||
if (strcmp(argv[i], "--no-randomx") == 0) {
|
||||
if (arg[0] == "no-randomx") {
|
||||
m_disableRandomX = true;
|
||||
ok = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((!strcmp(argv[i], "--out-peers") || !strcmp(argv[i], "--outpeers")) && (i + 1 < argc)) {
|
||||
m_maxOutgoingPeers = std::min(std::max(strtoul(argv[++i], nullptr, 10), 10UL), 450UL);
|
||||
if (((arg[0] == "out-peers") || (arg[0] == "outpeers")) && has1(arg)) {
|
||||
m_maxOutgoingPeers = std::min(std::max(strtoul(arg[1].c_str(), nullptr, 10), 10UL), 450UL);
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((!strcmp(argv[i], "--in-peers") || !strcmp(argv[i], "--inpeers")) && (i + 1 < argc)) {
|
||||
m_maxIncomingPeers = std::min(std::max(strtoul(argv[++i], nullptr, 10), 10UL), 450UL);
|
||||
if (((arg[0] == "in-peers") || (arg[0] == "inpeers")) && has1(arg)) {
|
||||
m_maxIncomingPeers = std::min(std::max(strtoul(arg[1].c_str(), nullptr, 10), 10UL), 450UL);
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--start-mining") == 0) && (i + 1 < argc)) {
|
||||
m_minerThreads = std::min(std::max(strtoul(argv[++i], nullptr, 10), 1UL), 64UL);
|
||||
if ((arg[0] == "start-mining") && has1(arg)) {
|
||||
m_minerThreads = std::min(std::max(strtoul(arg[1].c_str(), nullptr, 10), 1UL), 64UL);
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "--mini") == 0) {
|
||||
if (arg[0] == "mini") {
|
||||
m_mini = true;
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "--nano") == 0) {
|
||||
if (arg[0] == "nano") {
|
||||
m_nano = true;
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "--no-autodiff") == 0) {
|
||||
if (arg[0] == "no-autodiff") {
|
||||
m_autoDiff = false;
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--rpc-login") == 0) && (i + 1 < argc)) {
|
||||
if ((arg[0] == "rpc-login") && has1(arg)) {
|
||||
if (m_hosts.empty()) {
|
||||
m_hosts.emplace_back();
|
||||
}
|
||||
|
||||
m_hosts.back().m_rpcLogin = argv[++i];
|
||||
m_hosts.back().m_rpcLogin = arg[1];
|
||||
ok = true;
|
||||
}
|
||||
|
||||
#ifdef WITH_TLS
|
||||
if (strcmp(argv[i], "--rpc-ssl") == 0) {
|
||||
if (arg[0] == "rpc-ssl") {
|
||||
if (m_hosts.empty()) {
|
||||
m_hosts.emplace_back();
|
||||
}
|
||||
@@ -205,94 +218,90 @@ Params::Params(int argc, char* const argv[])
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--rpc-ssl-fingerprint") == 0) && (i + 1 < argc)) {
|
||||
if ((arg[0] == "rpc-ssl-fingerprint") && has1(arg)) {
|
||||
if (m_hosts.empty()) {
|
||||
m_hosts.emplace_back();
|
||||
}
|
||||
|
||||
m_hosts.back().m_rpcSSL_Fingerprint = argv[++i];
|
||||
m_hosts.back().m_rpcSSL_Fingerprint = arg[1];
|
||||
ok = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((strcmp(argv[i], "--socks5") == 0) && (i + 1 < argc)) {
|
||||
m_socks5Proxy = argv[++i];
|
||||
if ((arg[0] == "socks5") && has1(arg)) {
|
||||
m_socks5Proxy = arg[1];
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "--no-dns") == 0) {
|
||||
if (arg[0] == "no-dns") {
|
||||
m_dns = false;
|
||||
disable_resolve_host = true;
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--p2p-external-port") == 0) && (i + 1 < argc)) {
|
||||
m_p2pExternalPort = static_cast<int32_t>(std::min(std::max(strtoul(argv[++i], nullptr, 10), 1UL), 65535UL));
|
||||
if ((arg[0] == "p2p-external-port") && has1(arg)) {
|
||||
m_p2pExternalPort = static_cast<int32_t>(std::min(std::max(strtoul(arg[1].c_str(), nullptr, 10), 1UL), 65535UL));
|
||||
ok = true;
|
||||
}
|
||||
|
||||
#ifdef WITH_UPNP
|
||||
if ((strcmp(argv[i], "--no-upnp") == 0) || (strcmp(argv[i], "--no-igd") == 0)) {
|
||||
if ((arg[0] == "no-upnp") || (arg[0] == "no-igd")) {
|
||||
m_upnp = false;
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "--upnp-stratum") == 0) {
|
||||
if (arg[0] == "upnp-stratum") {
|
||||
m_upnpStratum = true;
|
||||
ok = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((strcmp(argv[i], "--merge-mine") == 0) && (i + 2 < argc)) {
|
||||
m_mergeMiningHosts.emplace_back(argv[i + 1], argv[i + 2]);
|
||||
i += 2;
|
||||
if ((arg[0] == "merge-mine") && has1(arg) && has2(arg)) {
|
||||
m_mergeMiningHosts.emplace_back(arg[1], arg[2]);
|
||||
ok = true;
|
||||
}
|
||||
|
||||
#ifdef WITH_TLS
|
||||
if ((strcmp(argv[i], "--tls-cert") == 0) && (i + 1 < argc)) {
|
||||
m_tlsCert = argv[++i];
|
||||
if ((arg[0] == "tls-cert") && has1(arg)) {
|
||||
m_tlsCert = arg[1];
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--tls-cert-key") == 0) && (i + 1 < argc)) {
|
||||
m_tlsCertKey = argv[++i];
|
||||
if ((arg[0] == "tls-cert-key") && has1(arg)) {
|
||||
m_tlsCertKey = arg[1];
|
||||
ok = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strcmp(argv[i], "--no-stratum-http") == 0) {
|
||||
if (arg[0] == "no-stratum-http") {
|
||||
m_enableStratumHTTP = false;
|
||||
ok = true;
|
||||
}
|
||||
|
||||
#ifdef WITH_MERGE_MINING_DONATION
|
||||
if ((strcmp(argv[i], "--adkf") == 0) && (i + 1 < argc)) {
|
||||
m_authorKeyFile = argv[++i];
|
||||
if ((arg[0] == "adkf") && has1(arg)) {
|
||||
m_authorKeyFile = arg[1];
|
||||
ok = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strcmp(argv[i], "--full-validation") == 0) {
|
||||
if (arg[0] == "full-validation") {
|
||||
m_enableFullValidation = true;
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if ((strcmp(argv[i], "--onion-address") == 0) && (i + 1 < argc)) {
|
||||
m_onionAddress = argv[++i];
|
||||
if ((arg[0] == "onion-address") && has1(arg)) {
|
||||
m_onionAddress = arg[1];
|
||||
ok = true;
|
||||
}
|
||||
|
||||
if (strcmp(argv[i], "--no-clearnet-p2p") == 0) {
|
||||
if (arg[0] == "no-clearnet-p2p") {
|
||||
m_noClearnetP2P = true;
|
||||
ok = true;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
fprintf(stderr, "Unknown command line parameter %s\n\n", argv[i]);
|
||||
fprintf(stderr, "Unknown or invalid command line parameter \"%s\"\n\n", arg[0].c_str());
|
||||
p2pool_usage();
|
||||
throw std::exception();
|
||||
}
|
||||
@@ -322,6 +331,23 @@ Params::Params(int argc, char* const argv[])
|
||||
m_hosts.emplace_back();
|
||||
}
|
||||
|
||||
const int p2p_port = m_mini ? DEFAULT_P2P_PORT_MINI : (m_nano ? DEFAULT_P2P_PORT_NANO : DEFAULT_P2P_PORT);
|
||||
|
||||
if (m_noClearnetP2P) {
|
||||
char buf[48] = {};
|
||||
log::Stream s(buf);
|
||||
s << "127.0.0.1:" << p2p_port;
|
||||
|
||||
m_p2pAddresses = buf;
|
||||
}
|
||||
else if (m_p2pAddresses.empty()) {
|
||||
char buf[48] = {};
|
||||
log::Stream s(buf);
|
||||
s << "[::]:" << p2p_port << ",0.0.0.0:" << p2p_port;
|
||||
|
||||
m_p2pAddresses = buf;
|
||||
}
|
||||
|
||||
if (m_stratumAddresses.empty()) {
|
||||
const int stratum_port = DEFAULT_STRATUM_PORT;
|
||||
|
||||
@@ -358,6 +384,43 @@ Params::Params(int argc, char* const argv[])
|
||||
}
|
||||
|
||||
m_displayWallet.assign(display_wallet_buf, Wallet::ADDRESS_LENGTH);
|
||||
|
||||
for (Params::Host& h : m_hosts) {
|
||||
if (!h.init_display_name(*this)) {
|
||||
throw std::exception();
|
||||
}
|
||||
}
|
||||
|
||||
// If the data directory is not set, check if P2Pool has write access to the current directory
|
||||
// If it doesn't, switch to user's home directory
|
||||
if (m_dataDir.empty()) {
|
||||
std::ofstream f("p2pool.tmp");
|
||||
if (f && f.put(' ')) {
|
||||
f.close();
|
||||
std::remove("p2pool.tmp");
|
||||
}
|
||||
else {
|
||||
char buf[1024];
|
||||
size_t size = sizeof(buf);
|
||||
|
||||
if (uv_os_homedir(buf, &size) == 0) {
|
||||
m_dataDir.assign(buf, size);
|
||||
fixup_path(m_dataDir);
|
||||
|
||||
m_dataDir += ".p2pool/";
|
||||
|
||||
if (m_mini) {
|
||||
m_dataDir += "mini/";
|
||||
}
|
||||
else if (m_nano) {
|
||||
m_dataDir += "nano/";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
fixup_path(m_dataDir);
|
||||
}
|
||||
}
|
||||
|
||||
bool Params::valid() const
|
||||
|
||||
+5
-2
@@ -29,7 +29,7 @@ struct Params
|
||||
FORCEINLINE Params() {}
|
||||
#endif
|
||||
|
||||
Params(int argc, char* const argv[]);
|
||||
explicit Params(const std::vector<std::vector<std::string>>& args);
|
||||
|
||||
bool valid() const;
|
||||
|
||||
@@ -65,7 +65,8 @@ struct Params
|
||||
|
||||
struct MergeMiningHost
|
||||
{
|
||||
MergeMiningHost(const char* host, const char* wallet) : m_host(host), m_wallet(wallet) {}
|
||||
template<typename T>
|
||||
FORCEINLINE MergeMiningHost(const T& host, const T& wallet) : m_host(host), m_wallet(wallet) {}
|
||||
|
||||
std::string m_host;
|
||||
std::string m_wallet;
|
||||
@@ -85,6 +86,8 @@ struct Params
|
||||
std::string m_stratumAddresses;
|
||||
std::string m_p2pAddresses;
|
||||
std::string m_p2pPeerList;
|
||||
std::string m_dataDir;
|
||||
std::string m_logFilePath;
|
||||
std::string m_sidechainConfig;
|
||||
std::string m_apiPath;
|
||||
uint64_t m_stratumBanTime = DEFAULT_STRATUM_BAN_TIME;
|
||||
|
||||
+2
-2
@@ -444,7 +444,7 @@ void RandomX_Hasher_RPC::loop(void* data)
|
||||
LOGINFO(1, "event loop stopped");
|
||||
}
|
||||
|
||||
bool RandomX_Hasher_RPC::calculate(const void* data_ptr, size_t size, uint64_t height, const hash& /*seed*/, hash& h, bool /*force_light_mode*/)
|
||||
bool RandomX_Hasher_RPC::calculate(const void* data_ptr, size_t size, uint64_t height, const hash& seed, hash& h, bool /*force_light_mode*/)
|
||||
{
|
||||
MutexLock lock(m_requestMutex);
|
||||
|
||||
@@ -456,7 +456,7 @@ bool RandomX_Hasher_RPC::calculate(const void* data_ptr, size_t size, uint64_t h
|
||||
s << "{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"calc_pow\",\"params\":{\"major_version\":" << major_version <<
|
||||
",\"height\":" << height <<
|
||||
",\"block_blob\":\"" << log::hex_buf(data, size) << '"' <<
|
||||
",\"seed_hash\":\"\"}}" << '\0';
|
||||
",\"seed_hash\":\"" << seed << "\"}}" << '\0';
|
||||
|
||||
std::atomic<int> result{ 0 };
|
||||
std::atomic<bool> done{ false };
|
||||
|
||||
+111
-2
@@ -27,6 +27,7 @@ extern "C" {
|
||||
#include <map>
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <fstream>
|
||||
|
||||
#if !defined(_WIN32) && defined(HAVE_SCHED)
|
||||
#include <sched.h>
|
||||
@@ -159,8 +160,6 @@ secure_zero_memory(volatile void* data, size_t size)
|
||||
|
||||
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)
|
||||
{
|
||||
switch (value) {
|
||||
@@ -1035,4 +1034,114 @@ hash from_onion_v3(const std::string& address)
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::vector<std::string>> parse_config(const std::string& file_name)
|
||||
{
|
||||
std::ifstream f(file_name);
|
||||
|
||||
if (!f.is_open() || !f.good()) {
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
std::vector<std::vector<std::string>> args;
|
||||
|
||||
auto is_alpha = [](char c) { return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'); };
|
||||
auto is_num = [](char c) { return ('0' <= c && c <= '9'); };
|
||||
|
||||
std::string s;
|
||||
|
||||
while (f.good() && std::getline(f, s)) {
|
||||
if (s.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool quoted = false;
|
||||
|
||||
enum {
|
||||
BEFORE_NAME,
|
||||
COMMENT,
|
||||
NAME,
|
||||
AFTER_NAME,
|
||||
VALUE,
|
||||
VALUE_ESCAPE_CHAR,
|
||||
} state = BEFORE_NAME;
|
||||
|
||||
for (const char c : s) {
|
||||
switch (state) {
|
||||
case BEFORE_NAME:
|
||||
if (is_alpha(c)) {
|
||||
state = NAME;
|
||||
args.emplace_back(1, std::string(1, c));
|
||||
}
|
||||
else if (c == '#') {
|
||||
state = COMMENT;
|
||||
}
|
||||
break;
|
||||
|
||||
case COMMENT:
|
||||
break;
|
||||
|
||||
case NAME:
|
||||
if (is_alpha(c) || is_num(c) || (c == '-')) {
|
||||
args.back()[0] += c;
|
||||
}
|
||||
else if (c == '#') {
|
||||
state = COMMENT;
|
||||
}
|
||||
else {
|
||||
state = AFTER_NAME;
|
||||
}
|
||||
break;
|
||||
|
||||
case AFTER_NAME:
|
||||
if (c == '#') {
|
||||
state = COMMENT;
|
||||
}
|
||||
else if ((c != '\t') && (c != ' ') && (c != '=')) {
|
||||
state = VALUE;
|
||||
quoted = (c == '"');
|
||||
if (quoted) {
|
||||
args.back().emplace_back();
|
||||
}
|
||||
else {
|
||||
args.back().emplace_back(1, c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VALUE:
|
||||
if (quoted) {
|
||||
if (c == '"') {
|
||||
state = AFTER_NAME;
|
||||
}
|
||||
else if (c == '\\') {
|
||||
state = VALUE_ESCAPE_CHAR;
|
||||
}
|
||||
else {
|
||||
args.back().back() += c;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (c == ' ') {
|
||||
state = AFTER_NAME;
|
||||
}
|
||||
else if (c == '#') {
|
||||
state = COMMENT;
|
||||
}
|
||||
else {
|
||||
args.back().back() += c;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VALUE_ESCAPE_CHAR:
|
||||
args.back().back() += c;
|
||||
state = VALUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
} // namespace p2pool
|
||||
|
||||
+3
-3
@@ -35,7 +35,7 @@
|
||||
namespace p2pool {
|
||||
|
||||
#define P2POOL_VERSION_MAJOR 4
|
||||
#define P2POOL_VERSION_MINOR 12
|
||||
#define P2POOL_VERSION_MINOR 13
|
||||
#define P2POOL_VERSION_PATCH 0
|
||||
|
||||
constexpr uint32_t P2POOL_VERSION = (P2POOL_VERSION_MAJOR << 16) | (P2POOL_VERSION_MINOR << 8) | P2POOL_VERSION_PATCH;
|
||||
@@ -44,8 +44,6 @@ extern const char* VERSION;
|
||||
|
||||
extern const uint8_t ED25519_MASTER_PUBLIC_KEY[32];
|
||||
|
||||
extern std::string DATA_DIR;
|
||||
|
||||
enum class SoftwareID : uint32_t {
|
||||
P2Pool = 0,
|
||||
GoObserver = 0x624F6F47UL,
|
||||
@@ -443,6 +441,8 @@ static FORCEINLINE constexpr hash from_onion_v3_const(const char* address)
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::vector<std::string>> parse_config(const std::string& file_name);
|
||||
|
||||
} // namespace p2pool
|
||||
|
||||
void memory_tracking_start();
|
||||
|
||||
@@ -191,3 +191,4 @@ add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMA
|
||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/src/sidechain_dump.dat.xz" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/src/sidechain_dump_mini.dat.xz" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/src/sidechain_dump_nano.dat.xz" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
||||
add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_SOURCE_DIR}/src/test_params.conf" $<TARGET_FILE_DIR:${CMAKE_PROJECT_NAME}>)
|
||||
|
||||
@@ -58,7 +58,7 @@ TEST(block_template, update)
|
||||
params.m_miningWallet = Wallet("44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg");
|
||||
|
||||
// Test 1: empty template
|
||||
tpl.update(data, mempool, ¶ms);
|
||||
tpl.update(data, mempool, params);
|
||||
ASSERT_EQ(tpl.get_reward(), 600000000000ULL);
|
||||
|
||||
const PoolBlock* b = tpl.pool_block_template();
|
||||
@@ -113,7 +113,7 @@ TEST(block_template, update)
|
||||
}
|
||||
ASSERT_EQ(mempool.size(), 512);
|
||||
|
||||
tpl.update(data, mempool, ¶ms);
|
||||
tpl.update(data, mempool, params);
|
||||
ASSERT_EQ(tpl.get_reward(), 612054770773ULL);
|
||||
|
||||
ASSERT_EQ(b->m_sidechainId, H("c9df4853003ab436416b9fc9a5a072d16b4dede849e697a8be2ebb9c88c8ec72"));
|
||||
@@ -154,7 +154,7 @@ TEST(block_template, update)
|
||||
|
||||
data.aux_chains.emplace_back(H("01f0cf665bd4cd31cbb2b2470236389c483522b350335e10a4a5dca34cb85990"), H("d9de1cfba7cdbd47f12f77addcb39b24c1ae7a16c35372bf28d6aee5d7579ee6"), difficulty_type(1000000));
|
||||
|
||||
tpl.update(data, mempool, ¶ms);
|
||||
tpl.update(data, mempool, params);
|
||||
ASSERT_EQ(tpl.get_reward(), 600300000000ULL);
|
||||
|
||||
ASSERT_EQ(b->m_sidechainId, H("c32abac2cad40e263a94f5f43f90e0a7d7d4b151305b79951dbc8c88c3180613"));
|
||||
@@ -191,7 +191,7 @@ TEST(block_template, update)
|
||||
}
|
||||
ASSERT_EQ(mempool.size(), 10000);
|
||||
|
||||
tpl.update(data, mempool, ¶ms);
|
||||
tpl.update(data, mempool, params);
|
||||
ASSERT_EQ(tpl.get_reward(), 619742028747ULL);
|
||||
|
||||
ASSERT_EQ(b->m_sidechainId, H("69e7dd43dd99ac6be3f57ca333cc0d814189e83aee1773c99a341aca085c0d46"));
|
||||
@@ -251,13 +251,13 @@ TEST(block_template, submit_sidechain_block)
|
||||
std::mt19937_64 rng(101112);
|
||||
|
||||
for (uint64_t i = 0, i2 = 0, i3 = 0; i < sidechain.chain_window_size() * 3; ++i) {
|
||||
tpl.update(data, mempool, ¶ms);
|
||||
tpl.update(data, mempool, params);
|
||||
|
||||
if ((rng() % 31) == 0) {
|
||||
tpl2.update(data, mempool, ¶ms);
|
||||
tpl2.update(data, mempool, params);
|
||||
|
||||
if ((rng() % 11) == 0) {
|
||||
tpl3.update(data, mempool, ¶ms);
|
||||
tpl3.update(data, mempool, params);
|
||||
++i3;
|
||||
ASSERT_TRUE(tpl3.submit_sidechain_block(i3, 0, 0));
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ TEST(pool_block, verify)
|
||||
params.m_miningWallet = Wallet("44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg");
|
||||
params.m_subaddress = Wallet("86eQxzSW4AZfvsWRSop755WZUsog6L3x32NRZukeeShnS4mBGVpcqQhS6pCNxj44usPKNwesZ45ooHyjDku6nVZdT3Q9qrz");
|
||||
|
||||
tpl.update(data, mempool, ¶ms);
|
||||
tpl.update(data, mempool, params);
|
||||
|
||||
std::vector<uint8_t> blobs;
|
||||
uint64_t height;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# comment 1
|
||||
|
||||
param1=value1
|
||||
param2 = value2 # comment 2
|
||||
param3 value3#_comment_3
|
||||
|
||||
param4 = "value with spaces # not a comment" # a real comment
|
||||
param5 = "spaces and quotes \" and \\ slashes"
|
||||
|
||||
param6 = value1 value2 value3
|
||||
|
||||
param7=value7
|
||||
|
||||
param8#comment
|
||||
param9
|
||||
|
||||
abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789=0123456789-ABCDEFGHIJKLMNOPQRSTUVWXYZ-abcdefghijklmnopqrstuvwxyz=://
|
||||
@@ -247,4 +247,65 @@ TEST(util, onion)
|
||||
ASSERT_TRUE(from_onion_v3("civ5tgldg3yx73ytse6hvvk3nm6q3zctbqvytpszihm35b33ze73kxad.onion").empty());
|
||||
}
|
||||
|
||||
TEST(util, parse_config)
|
||||
{
|
||||
const std::vector<std::vector<std::string>> args = parse_config("test_params.conf");
|
||||
|
||||
ASSERT_EQ(args.size(), 10);
|
||||
|
||||
ASSERT_EQ(args[0].size(), 2);
|
||||
ASSERT_EQ(args[0][0], "param1");
|
||||
ASSERT_EQ(args[0][1], "value1");
|
||||
|
||||
ASSERT_EQ(args[1].size(), 2);
|
||||
ASSERT_EQ(args[1][0], "param2");
|
||||
ASSERT_EQ(args[1][1], "value2");
|
||||
|
||||
ASSERT_EQ(args[2].size(), 2);
|
||||
ASSERT_EQ(args[2][0], "param3");
|
||||
ASSERT_EQ(args[2][1], "value3");
|
||||
|
||||
ASSERT_EQ(args[3].size(), 2);
|
||||
ASSERT_EQ(args[3][0], "param4");
|
||||
ASSERT_EQ(args[3][1], "value with spaces # not a comment");
|
||||
|
||||
ASSERT_EQ(args[4].size(), 2);
|
||||
ASSERT_EQ(args[4][0], "param5");
|
||||
ASSERT_EQ(args[4][1], "spaces and quotes \" and \\ slashes");
|
||||
|
||||
ASSERT_EQ(args[5].size(), 4);
|
||||
ASSERT_EQ(args[5][0], "param6");
|
||||
ASSERT_EQ(args[5][1], "value1");
|
||||
ASSERT_EQ(args[5][2], "value2");
|
||||
ASSERT_EQ(args[5][3], "value3");
|
||||
|
||||
ASSERT_EQ(args[6].size(), 2);
|
||||
ASSERT_EQ(args[6][0], "param7");
|
||||
ASSERT_EQ(args[6][1], "value7");
|
||||
|
||||
ASSERT_EQ(args[7].size(), 1);
|
||||
ASSERT_EQ(args[7][0], "param8");
|
||||
|
||||
ASSERT_EQ(args[8].size(), 1);
|
||||
ASSERT_EQ(args[8][0], "param9");
|
||||
|
||||
ASSERT_EQ(args[9].size(), 2);
|
||||
ASSERT_EQ(args[9][0], "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ-0123456789");
|
||||
ASSERT_EQ(args[9][1], "0123456789-ABCDEFGHIJKLMNOPQRSTUVWXYZ-abcdefghijklmnopqrstuvwxyz=://");
|
||||
|
||||
bool exception_thrown = false;
|
||||
|
||||
try {
|
||||
parse_config("non_existent_file.conf");
|
||||
|
||||
// Execution shouldn't reach this line
|
||||
FAIL();
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
exception_thrown = true;
|
||||
}
|
||||
|
||||
ASSERT_TRUE(exception_thrown);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user