From 6e4865c14c858d00c6cfa6967e66a86b31cd12f8 Mon Sep 17 00:00:00 2001 From: bitflash-maintainer Date: Sat, 8 Aug 2026 02:29:26 +0000 Subject: pool: sync-gate job creation, retry failed payouts; widen nostr relay set - RebuildJob: no jobs with zero peers or a tip older than 30min; mining unsynced produced orphaned blocks and payouts that can never be paid (observed in production: 8 orphan 'found blocks') - payout exec: on SendMoney failure requeue with 60s backoff, up to 30 attempts, instead of silently forfeiting the payment - nostr: add oxtr.dev, nos.social, fmt.wiz.biz, current.fyi, nostr.bg (12 relays total) for announcement redundancy (cherry picked from commit f1986cd7e4a6f69469a2256eb96ff03f3f146792) --- src/net.cpp | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) (limited to 'src/net.cpp') diff --git a/src/net.cpp b/src/net.cpp index 449d91c..5cf2f8c 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1054,6 +1054,18 @@ CNode* ConnectNodeBtfResolved(const string& strBtfAddr, const string& strMeeting void ThreadBtfAccept(void* parg) { printf("ThreadBtfAccept started\n"); + // In operator mode the pool server registers this same node identity as a + // stratum service at the rendezvous relays, and a relay only holds ONE + // service registration per pubkey -- peer-accept and pool-accept would + // kick each other off forever, breaking both. The pool's registration is + // the one that must be stable (that's what miners resolve and dial), so + // the node skips inbound rendezvous here and relies on outbound .btf + // connections for block sync. + if (nMineMode == MINE_OPERATOR) + { + printf("ThreadBtfAccept: operator mode -- skipping peer rendezvous registration\n"); + return; + } unsigned char pk[32]; unsigned char sk[32]; while (!BtfGetIdentity(pk, sk)) @@ -1928,11 +1940,29 @@ bool StartNode(string& strError) { int nErr = WSAGetLastError(); if (nErr == WSAEADDRINUSE) - strError = strprintf("Error: Unable to bind to port %s on this computer. The program is probably already running.", addrLocalHost.ToString().c_str()); + { + // Another local instance holds the default port. Fall back to an + // ephemeral port: inbound direct-IP peering is optional, and .btf + // rendezvous connectivity is unaffected by the local listen port. + sockaddr.sin_port = htons(0); + if (bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR) + { + strError = strprintf("Error: Unable to bind any port on this computer (bind returned error %d)", WSAGetLastError()); + printf("%s\n", strError.c_str()); + return false; + } + struct sockaddr_in bound; + socklen_t nBoundLen = sizeof(bound); + if (getsockname(hListenSocket, (struct sockaddr*)&bound, &nBoundLen) == 0) + addrLocalHost.port = bound.sin_port; + printf("default port in use by another instance; bound to ephemeral %s instead\n", addrLocalHost.ToString().c_str()); + } else + { strError = strprintf("Error: Unable to bind to port %s on this computer (bind returned error %d)", addrLocalHost.ToString().c_str(), nErr); - printf("%s\n", strError.c_str()); - return false; + printf("%s\n", strError.c_str()); + return false; + } } printf("bound to addrLocalHost = %s\n\n", addrLocalHost.ToString().c_str()); -- cgit v1.2.3