Skip to content

Commit

Permalink
Added support for multiple Monero hosts
Browse files Browse the repository at this point in the history
Switch to the next host in list when P2Pool thinks current host is stuck or lagging
  • Loading branch information
SChernykh committed Jun 18, 2023
1 parent 192f1d7 commit b5fa34e
Show file tree
Hide file tree
Showing 15 changed files with 402 additions and 147 deletions.
18 changes: 6 additions & 12 deletions .github/workflows/test-sync.yml
Expand Up @@ -32,14 +32,13 @@ jobs:
make -j$(nproc)
- name: Run p2pool
timeout-minutes: 25
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 &
TSAN_OPTIONS="suppressions=../tests/src/tsan_sup.txt halt_on_error=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
TSAN_OPTIONS="suppressions=../tests/src/tsan_sup.txt halt_on_error=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
grep 'Synchronization finished successfully' p2pool.log
- name: Archive p2pool.log
Expand Down Expand Up @@ -110,14 +109,13 @@ jobs:
make -j$(nproc)
- name: Run p2pool
timeout-minutes: 20
run: |
cd build
mkdir data
python ../tests/src/stratum_dummy.py 1 &
python ../tests/src/stratum_dummy.py 2 &
python ../tests/src/stratum_dummy.py 3 &
MSAN_OPTIONS="halt_on_error=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
MSAN_OPTIONS="halt_on_error=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
grep 'Synchronization finished successfully' p2pool.log
- name: Archive p2pool.log
Expand Down Expand Up @@ -153,14 +151,13 @@ jobs:
make -j$(nproc)
- name: Run p2pool
timeout-minutes: 20
run: |
cd build
mkdir data
python ../tests/src/stratum_dummy.py 1 &
python ../tests/src/stratum_dummy.py 2 &
python ../tests/src/stratum_dummy.py 3 &
UBSAN_OPTIONS="suppressions=../tests/src/ubsan_sup.txt halt_on_error=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
UBSAN_OPTIONS="suppressions=../tests/src/ubsan_sup.txt halt_on_error=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
grep 'Synchronization finished successfully' p2pool.log
- name: Archive p2pool.log
Expand Down Expand Up @@ -196,14 +193,13 @@ jobs:
make -j$(nproc)
- name: Run p2pool
timeout-minutes: 20
run: |
cd build
mkdir data
python ../tests/src/stratum_dummy.py 1 &
python ../tests/src/stratum_dummy.py 2 &
python ../tests/src/stratum_dummy.py 3 &
ASAN_OPTIONS="detect_stack_use_after_return=1 atexit=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
ASAN_OPTIONS="detect_stack_use_after_return=1 atexit=1" ./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
grep 'Synchronization finished successfully' p2pool.log
- name: Archive p2pool.log
Expand Down Expand Up @@ -236,14 +232,13 @@ jobs:
make -j3
- name: Run p2pool
timeout-minutes: 20
run: |
cd build
mkdir data
python ../tests/src/stratum_dummy.py 1 &
python ../tests/src/stratum_dummy.py 2 &
python ../tests/src/stratum_dummy.py 3 &
./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
./p2pool --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
grep 'Synchronization finished successfully' p2pool.log
- name: Archive p2pool.log
Expand Down Expand Up @@ -276,14 +271,13 @@ jobs:
& "C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Msbuild\\Current\\Bin\\amd64\\msbuild" /m /p:Configuration=Debug p2pool.vcxproj
- name: Run p2pool
timeout-minutes: 20
run: |
cd build/Debug
mkdir data
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 1"
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 2"
Start-Process python -ArgumentList "../../tests/src/stratum_dummy.py 3"
./p2pool.exe --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
./p2pool.exe --host xmrnode.facspro.net --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --data-api data --local-api --loglevel 6
findstr /C:"Synchronization finished successfully" p2pool.log
- name: Archive p2pool.log
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Expand Up @@ -120,7 +120,7 @@ if (WITH_RANDOMX)
set(SOURCES ${SOURCES} src/miner.cpp)
endif()

if (NOT STATIC_BINARY AND NOT STATIC_LIBS)
if (NOT ((CMAKE_CXX_COMPILER_ID MATCHES MSVC) OR STATIC_BINARY OR STATIC_LIBS))
include(FindCURL)
endif()

Expand Down
13 changes: 13 additions & 0 deletions docs/COMMAND_LINE.MD
Expand Up @@ -34,4 +34,17 @@

### Example command line

```
p2pool.exe --host 127.0.0.1 --rpc-port 18081 --zmq-port 18083 --wallet YOUR_WALLET_ADDRESS --stratum 0.0.0.0:3333 --p2p 0.0.0.0:37889
```

### Multiple backup hosts

You can have multiple hosts in command line. Each new host uses RPC and zmq-pub port numbers from the previous host (or default 18081/18083 if none were specified).

In this example, you have local Monero node running on ports 18081/18083 (RPC/zmq-pub), and several backup nodes running on ports 18089/18084. If P2Pool detects that the node it's currently using is unavailable or stuck, it will cycle to the next node in the list.


```
p2pool.exe --host 127.0.0.1 --host xmr1.rs.me --rpc-port 18089 --zmq-port 18084 --host xmr2.rs.me --host xmr3.rs.me --wallet YOUR_WALLET_ADDRESS
```
16 changes: 15 additions & 1 deletion src/console_commands.cpp
Expand Up @@ -140,7 +140,7 @@ typedef struct cmd {
cmdfunc *func;
} cmd;

static cmdfunc do_help, do_status, do_loglevel, do_addpeers, do_droppeers, do_showpeers, do_showworkers, do_showbans, do_outpeers, do_inpeers, do_exit, do_version;
static cmdfunc do_help, do_status, do_loglevel, do_addpeers, do_droppeers, do_showpeers, do_showworkers, do_showbans, do_showhosts, do_nexthost, do_outpeers, do_inpeers, do_exit, do_version;

#ifdef WITH_RANDOMX
static cmdfunc do_start_mining, do_stop_mining;
Expand All @@ -155,6 +155,8 @@ static cmd cmds[] = {
{ STRCONST("peers"), "", "show all peers", do_showpeers },
{ STRCONST("workers"), "", "show all connected workers", do_showworkers },
{ STRCONST("bans"), "", "show all banned IPs", do_showbans },
{ STRCONST("hosts"), "", "show Monero hosts", do_showhosts },
{ STRCONST("next_host"), "", "switch to the next Monero host", do_nexthost },
{ STRCONST("outpeers"), "<N>", "set maximum number of outgoing connections", do_outpeers },
{ STRCONST("inpeers"), "<N>", "set maximum number of incoming connections", do_inpeers },
#ifdef WITH_RANDOMX
Expand Down Expand Up @@ -240,6 +242,18 @@ static void do_showbans(p2pool* m_pool, const char* /* args */)
}
}

// cppcheck-suppress constParameterCallback
static void do_showhosts(p2pool* m_pool, const char* /* args */)
{
m_pool->print_hosts();
}

// cppcheck-suppress constParameterCallback
static void do_nexthost(p2pool* m_pool, const char* /* args */)
{
m_pool->reconnect_to_host();
}

// cppcheck-suppress constParameterCallback
static void do_outpeers(p2pool* m_pool, const char* args)
{
Expand Down
34 changes: 26 additions & 8 deletions src/p2p_server.cpp
Expand Up @@ -615,9 +615,9 @@ void P2PServer::load_peer_list()

void P2PServer::load_monerod_peer_list()
{
const Params& params = m_pool->params();
const Params::Host host = m_pool->current_host();

JSONRPCRequest::call(params.m_host, params.m_rpcPort, "/get_peer_list", params.m_rpcLogin, m_socks5Proxy,
JSONRPCRequest::call(host.m_address, host.m_rpcPort, "/get_peer_list", host.m_rpcLogin, m_socks5Proxy,
[this](const char* data, size_t size)
{
#define ERR_STR "/get_peer_list RPC request returned invalid JSON "
Expand Down Expand Up @@ -1045,7 +1045,7 @@ void P2PServer::on_timer()
update_peer_list();
save_peer_list_async();
update_peer_connections();
check_zmq();
check_host();
check_block_template();
api_update_local_stats();
}
Expand Down Expand Up @@ -1165,25 +1165,41 @@ void P2PServer::download_missing_blocks()
}
}

void P2PServer::check_zmq()
void P2PServer::check_host()
{
if ((m_timerCounter % 30) != 3) {
if (!m_pool->startup_finished()) {
return;
}

if (!m_pool->zmq_running()) {
LOGERR(1, "ZMQ is not running, restarting it");
m_pool->restart_zmq();
m_pool->reconnect_to_host();
return;
}

const uint64_t height = m_pool->miner_data().height;
const SideChain& side_chain = m_pool->side_chain();

// If the latest 5 side chain blocks are 2 or more Monero blocks ahead, then the node is probably stuck
uint32_t counter = 5;
for (const PoolBlock* b = side_chain.chainTip(); b && (b->m_txinGenHeight >= height + 2); b = side_chain.find_block(b->m_parent)) {
if (--counter == 0) {
const Params::Host host = m_pool->current_host();
LOGERR(1, host.m_displayName << " seems to be stuck, reconnecting");
m_pool->reconnect_to_host();
return;
}
}

const uint64_t cur_time = seconds_since_epoch();
const uint64_t last_active = m_pool->zmq_last_active();

// If there were no ZMQ messages in the last 5 minutes, then the node is probably stuck
if (cur_time >= last_active + 300) {
const uint64_t dt = static_cast<uint64_t>(cur_time - last_active);
LOGERR(1, "no ZMQ messages received from monerod in the last " << dt << " seconds, check your monerod/p2pool/network/firewall setup!!!");
m_pool->restart_zmq();
const Params::Host host = m_pool->current_host();
LOGERR(1, "no ZMQ messages received from " << host.m_displayName << " in the last " << dt << " seconds, check your monerod/p2pool/network/firewall setup!!!");
m_pool->reconnect_to_host();
}
}

Expand Down Expand Up @@ -1230,6 +1246,8 @@ P2PServer::P2PClient::P2PClient()

void P2PServer::on_shutdown()
{
save_peer_list();

uv_timer_stop(&m_timer);
uv_close(reinterpret_cast<uv_handle_t*>(&m_timer), nullptr);
uv_close(reinterpret_cast<uv_handle_t*>(&m_broadcastAsync), nullptr);
Expand Down
2 changes: 1 addition & 1 deletion src/p2p_server.h
Expand Up @@ -191,7 +191,7 @@ class P2PServer : public TCPServer

void flush_cache();
void download_missing_blocks();
void check_zmq();
void check_host();
void check_block_template();
void update_peer_connections();
void update_peer_list();
Expand Down

0 comments on commit b5fa34e

Please sign in to comment.