upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/rpc.cpp
diff options
context:
space:
mode:
authorbitflash-maintainer <noreply@bitflash.invalid>2026-09-02 14:46:38 +0000
committerbitflash-maintainer <noreply@bitflash.invalid>2026-09-02 14:46:38 +0000
commit9a409d8ba97251f29ba80913a4014b8a369c52c0 (patch)
treeb3e5d74b827f29af8fe36a4409abdde8259e50b2 /src/rpc.cpp
parente4f898c4a6b9900553c64b9804889b5fdae3e55f (diff)
pool: advertise a rendezvous only once registered, and log the pin
Issue #2 reported that /rvrelay does not govern registration. It does: BtfAllRelays() returns vBtfMeetingRelays alone when fBtfRelayPinned, and every relay-choosing site -- the pool's AcceptLoopFn, the node's ThreadBtfAccept, and the dial path -- draws from it. vBtfMeetingRelays has exactly one writer, the pin itself. A pinned pool therefore spawns one accept thread, at the pin, and no discovered relay is registered at. The registration the incident actually caught was not the pool's. The "registered at" line it quotes exists only in ThreadBtfAccept, and 90.156.222.107:8434 is not a stranger's relay -- it is the third hardcoded seed, one of the three ThreadBtfAccept picks between at random when no pin is in force. That relay is only reachable with the pin absent, so the binary that logged it did not have one; both the pin and the operator-mode skip that keeps a pool out of that thread landed two days before the observation. What was genuinely wrong is that none of this could be read off a log. The pool announced no successful registration at all, and retried failures at one flat line, so "is this pool registered where its descriptor says" had no answer. So: - Advertise the relay after registering at it, not before. The optimistic order published a meeting node we were not yet listed at, and a miner resolving the descriptor inside that window spent its dial on a relay holding no registration for us. ThreadBtfAccept has always ordered it this way; the pool had not. - Log the relay registration succeeds at, name the pin when one is in force, and name each discovered relay the pin excludes. - Escalate when a pinned relay keeps refusing: a pin has no fallback, so an unregistered pin means the pool is unreachable, and that now says so instead of scrolling past. - Refuse to advertise a non-pinned relay in BtfSetActiveRelay. No caller can reach it today, but the descriptor is the one thing a miner obeys, so the invariant is enforced at the sink rather than retrusted to every future caller. Does not touch the registration-consumption race: the pool still gives up its registration on each pairing and re-registers after wrap-and-push. Moving the advertise call inside that loop does not widen the window, it only stops the descriptor naming a relay we never reached.
Diffstat (limited to 'src/rpc.cpp')
-rw-r--r--src/rpc.cpp61
1 files changed, 52 insertions, 9 deletions
diff --git a/src/rpc.cpp b/src/rpc.cpp
index a4b53ca..a3560ff 100644
--- a/src/rpc.cpp
+++ b/src/rpc.cpp
@@ -4947,13 +4947,19 @@ static void AcceptOneFn(void* arg)
4947 std::string host = relay.substr(0, colon); 4947 std::string host = relay.substr(0, colon);
4948 int port = atoi(relay.substr(colon + 1).c_str()); 4948 int port = atoi(relay.substr(colon + 1).c_str());
4949 4949
4950 LogPrint("pool", "[pool] accept thread started for relay %s\n", relay.c_str()); 4950 LogPrint("pool", "[pool] accept thread started for relay %s%s\n", relay.c_str(),
4951 fBtfRelayPinned ? " (/rvrelay pin)" : "");
4952
4953 // Registration health for this relay. A pin has no fallback, so a pin that
4954 // never registers means the pool is simply unreachable -- and that has to
4955 // be loud. The 2026-07-30 incident went unnoticed because this loop logged
4956 // failures at one flat line and success not at all, so "which relay is this
4957 // pool actually registered at" could not be answered from the log.
4958 int nConsecFail = 0;
4959 int64 nFirstFail = 0;
4960 bool fEverRegistered = false;
4951 4961
4952 while (!fShutdown && gPoolRunning) { 4962 while (!fShutdown && gPoolRunning) {
4953 // Advertise this relay as the pool's meeting node BEFORE registering,
4954 // so that miners which resolve our descriptor find a relay where the
4955 // pool (not the node's peer-accept) holds the registration.
4956 BtfSetActiveRelay(relay);
4957 // Returns as soon as the relay lists us -- registered, not yet paired. 4963 // Returns as soon as the relay lists us -- registered, not yet paired.
4958 btf::RvSocket rv = btf::RvServiceRegister(host.c_str(), (unsigned short)port, pk); 4964 btf::RvSocket rv = btf::RvServiceRegister(host.c_str(), (unsigned short)port, pk);
4959 4965
@@ -4962,12 +4968,36 @@ static void AcceptOneFn(void* arg)
4962 break; 4968 break;
4963 } 4969 }
4964 if (rv == btf::RV_INVALID) { 4970 if (rv == btf::RV_INVALID) {
4965 LogPrint("pool", "[pool] relay %s: RvServiceRegister failed" 4971 nConsecFail++;
4966 " -- backing off 30s before retry\n", relay.c_str()); 4972 if (nFirstFail == 0) nFirstFail = GetTime();
4973 LogPrint("pool", "[pool] relay %s: registration failed (attempt %d,"
4974 " failing for %llds) -- backing off 30s before retry\n",
4975 relay.c_str(), nConsecFail, (long long)(GetTime() - nFirstFail));
4976 if (fBtfRelayPinned && (nConsecFail == 3 || nConsecFail % 10 == 0))
4977 LogPrint("pool", "[pool] WARNING: pinned relay %s refused registration"
4978 " %d times running (%llds); /rvrelay leaves no fallback, so"
4979 " miners cannot reach this pool%s\n",
4980 relay.c_str(), nConsecFail, (long long)(GetTime() - nFirstFail),
4981 fEverRegistered ? "" : " -- it has never registered once");
4967 for (int i = 0; i < 30 && !fShutdown && gPoolRunning; i++) Sleep(1000); 4982 for (int i = 0; i < 30 && !fShutdown && gPoolRunning; i++) Sleep(1000);
4968 continue; 4983 continue;
4969 } 4984 }
4970 4985
4986 // Advertise THIS relay only now. Setting it before the call published a
4987 // meeting node we were not yet listed at, so a miner resolving the
4988 // descriptor inside that window burned its dial on a relay holding no
4989 // registration for us. net.cpp's peer-accept has always ordered it this
4990 // way round; the pool had not.
4991 BtfSetActiveRelay(relay);
4992 if (!fEverRegistered || nConsecFail > 0)
4993 LogPrint("pool", "[pool] registered at relay %s%s%s -- advertising it as"
4994 " the pool's meeting node\n", relay.c_str(),
4995 fBtfRelayPinned ? " (/rvrelay pin)" : "",
4996 nConsecFail > 0 ? ", recovered" : "");
4997 fEverRegistered = true;
4998 nConsecFail = 0;
4999 nFirstFail = 0;
5000
4971 // Block for a miner to actually arrive. RvServiceRegister used to do 5001 // Block for a miner to actually arrive. RvServiceRegister used to do
4972 // this itself and returned with the relay's 0x01 pairing byte already 5002 // this itself and returned with the relay's 0x01 pairing byte already
4973 // consumed; it no longer does. Without waiting here, BtfServiceWrap 5003 // consumed; it no longer does. Without waiting here, BtfServiceWrap
@@ -5022,9 +5052,21 @@ static void AcceptLoopFn(void*)
5022 LogPrint("pool", "[pool] .btf identity ready after %ds\n", waitSecs * 2); 5052 LogPrint("pool", "[pool] .btf identity ready after %ds\n", waitSecs * 2);
5023 5053
5024 std::set<std::string> spawned; // relays we've already started a thread for 5054 std::set<std::string> spawned; // relays we've already started a thread for
5055 std::set<std::string> skipped; // discovered relays the pin excluded, logged once each
5025 5056
5026 while (!fShutdown && gPoolRunning) { 5057 while (!fShutdown && gPoolRunning) {
5058 // BtfAllRelays() already honours the pin: with /rvrelay set it returns
5059 // vBtfMeetingRelays alone, so no thread is ever spawned for a
5060 // discovered relay. Name the ones it drops -- a pool registering at a
5061 // stranger's relay is exactly the thing that should not be silent.
5027 vector<string> relays = BtfAllRelays(); 5062 vector<string> relays = BtfAllRelays();
5063 if (fBtfRelayPinned) {
5064 for (const string& r : BtfDiscoveredRelays())
5065 if (std::find(relays.begin(), relays.end(), r) == relays.end() &&
5066 skipped.insert(r).second)
5067 LogPrint("pool", "[pool] not registering at discovered relay %s"
5068 " -- /rvrelay pins the relay list\n", r.c_str());
5069 }
5028 if (relays.empty()) { 5070 if (relays.empty()) {
5029 LogPrint("pool", "[pool] no relays available -- miners cannot connect yet\n"); 5071 LogPrint("pool", "[pool] no relays available -- miners cannot connect yet\n");
5030 } else { 5072 } else {
@@ -5040,8 +5082,9 @@ static void AcceptLoopFn(void*)
5040 relay.c_str()); 5082 relay.c_str());
5041 } else { 5083 } else {
5042 spawned.insert(relay); 5084 spawned.insert(relay);
5043 LogPrint("pool", "[pool] accept thread spawned for relay %s" 5085 LogPrint("pool", "[pool] accept thread spawned for relay %s%s"
5044 " (%zu total)\n", relay.c_str(), spawned.size()); 5086 " (%zu total)\n", relay.c_str(),
5087 fBtfRelayPinned ? " (/rvrelay pin)" : "", spawned.size());
5045 } 5088 }
5046 } 5089 }
5047 } 5090 }