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/btfrv.cpp | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) (limited to 'src/btfrv.cpp') diff --git a/src/btfrv.cpp b/src/btfrv.cpp index 6ac3280..905717f 100644 --- a/src/btfrv.cpp +++ b/src/btfrv.cpp @@ -94,31 +94,42 @@ static SOCKET ConnectTo(const char* host, unsigned short port) { struct addrinfo hints, *res = NULL; memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; + hints.ai_family = AF_UNSPEC; // IPv4 or IPv6 (some relays are v6-only) hints.ai_socktype = SOCK_STREAM; char portstr[16]; sprintf(portstr, "%u", (unsigned)port); if (getaddrinfo(host, portstr, &hints, &res) != 0 || !res) return INVALID_SOCKET; - SOCKET s = BtfSocketTag(socket(res->ai_family, res->ai_socktype, res->ai_protocol), SOCK_RV_DIAL); - if (s == INVALID_SOCKET) { freeaddrinfo(res); return INVALID_SOCKET; } - // Apply a short timeout only for the connect() and initial handshake so an - // unresponsive relay doesn't block the thread. Once the tunnel is live the - // timeout is cleared -- a forwarding pipe must block indefinitely on recv(). + // Try each resolved address until one connects. + SOCKET s = INVALID_SOCKET; + for (struct addrinfo* rp = res; rp != NULL; rp = rp->ai_next) + { + s = BtfSocketTag(socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol), SOCK_RV_DIAL); + if (s == INVALID_SOCKET) + continue; + + // Apply a short timeout only for the connect() and initial handshake so an + // unresponsive relay doesn't block the thread. Once the tunnel is live the + // timeout is cleared -- a forwarding pipe must block indefinitely on recv(). #ifdef _WIN32 - DWORD tvShort = 10000; - setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tvShort, sizeof(tvShort)); - setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tvShort, sizeof(tvShort)); + DWORD tvShort = 10000; + setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tvShort, sizeof(tvShort)); + setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tvShort, sizeof(tvShort)); #else - struct timeval tvShort; tvShort.tv_sec = 10; tvShort.tv_usec = 0; - setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tvShort, sizeof(tvShort)); - setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, &tvShort, sizeof(tvShort)); + struct timeval tvShort; tvShort.tv_sec = 10; tvShort.tv_usec = 0; + setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&tvShort, sizeof(tvShort)); + setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*)&tvShort, sizeof(tvShort)); #endif - if (connect(s, res->ai_addr, (int)res->ai_addrlen) != 0) - { - CLOSESOCK(s); freeaddrinfo(res); return INVALID_SOCKET; + if (connect(s, rp->ai_addr, (int)rp->ai_addrlen) != 0) + { + CLOSESOCK(s); + s = INVALID_SOCKET; + continue; + } + break; } freeaddrinfo(res); + if (s == INVALID_SOCKET) return INVALID_SOCKET; // Clear the timeout -- the socket is now a live tunnel and must not // time out when idle. recv() will block until data arrives or peer closes. -- cgit v1.2.3