From 014798e50b2de37ed5243c7e622fc290dfda8606 Mon Sep 17 00:00:00 2001 From: bitflash-maintainer Date: Wed, 2 Sep 2026 09:03:33 +0000 Subject: worker: fail over across seed relays when the advertised meeting node keeps failing --- src/main.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index c0a8825..0414714 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3739,6 +3739,33 @@ static bool PoolParticipantMiner() } LogPrint("worker", "[worker] pool resolved to meeting node %s\n", meetingHostPort.c_str()); + // The descriptor names ONE meeting node, but the pool parks a + // registration at every relay it knows (one accept thread per relay, + // rpc.cpp:AcceptOneFn), so any seed relay can pair us. Insisting on the + // advertised entry forever turns one bad path into a miner that idles + // indefinitely while a working path exists (issue #17); after a few + // consecutive tunnel failures, rotate the seed relays into the attempts + // too. Only ONE participant session runs (StartMinerThreads), so these + // statics are single-threaded. + static const int TUNNEL_FAILOVER_AFTER = 3; + static int nTunnelFails = 0; // consecutive tunnel failures, this pool + static size_t iFailoverRelay = 0; // rotation cursor over vBtfMeetingRelays + static std::string strFailPool; // pool the counters belong to + if (strFailPool != strParticipantPool) { + strFailPool = strParticipantPool; + nTunnelFails = 0; + iFailoverRelay = 0; + } + if (nTunnelFails >= TUNNEL_FAILOVER_AFTER && !vBtfMeetingRelays.empty()) { + std::string alt = vBtfMeetingRelays[iFailoverRelay++ % vBtfMeetingRelays.size()]; + if (alt != meetingHostPort) { + LogPrint("worker", "[worker] advertised meeting node %s failed %d" + " times in a row -- trying seed relay %s instead\n", + meetingHostPort.c_str(), nTunnelFails, alt.c_str()); + meetingHostPort = alt; + } + } + size_t colon = meetingHostPort.rfind(':'); if (colon == std::string::npos) { LogPrint("worker", "[worker] bad meeting node format '%s'\n", meetingHostPort.c_str()); @@ -3762,12 +3789,14 @@ static bool PoolParticipantMiner() s = btf::BtfClientTunnel(host.c_str(), (unsigned short)port, target_pubkey, service_enc_pub, &tunnelFail); if (s == INVALID_SOCKET) { + nTunnelFails++; LogPrint("worker", "[worker] tunnel connect FAILED via %s: %s\n", meetingHostPort.c_str(), btf::TunnelFailText(tunnelFail)); SetParticipantMiningStatus(std::string("tunnel connect failed: ") + btf::TunnelFailText(tunnelFail)); return false; } + nTunnelFails = 0; LogPrint("worker", "[worker] tunnel open via %s\n", meetingHostPort.c_str()); SetParticipantMiningStatus("tunnel open"); } -- cgit v1.2.3