diff options
Diffstat (limited to 'src/nostr.cpp')
| -rw-r--r-- | src/nostr.cpp | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/src/nostr.cpp b/src/nostr.cpp index 088174a..17139ad 100644 --- a/src/nostr.cpp +++ b/src/nostr.cpp | |||
| @@ -83,7 +83,11 @@ static CCriticalSection cs_btfPeers; | |||
| 83 | const char* pszNostrRelays[] = { | 83 | const char* pszNostrRelays[] = { |
| 84 | "wss://relay.damus.io", | 84 | "wss://relay.damus.io", |
| 85 | "wss://nos.lol", | 85 | "wss://nos.lol", |
| 86 | "wss://relay.nostr.band", | 86 | // Was relay.nostr.band, which went down and stayed down (2026-07-31: |
| 87 | // resolves, refuses TCP on 443, from several networks). Replaced with a | ||
| 88 | // relay on a different upstream again -- 206.245.132.32, neither | ||
| 89 | // Cloudflare nor Hetzner, which the rest of this list already leans on. | ||
| 90 | "wss://nostr.bitcoiner.social", | ||
| 87 | "wss://nostr21.com", | 91 | "wss://nostr21.com", |
| 88 | "wss://offchain.pub", | 92 | "wss://offchain.pub", |
| 89 | "wss://nostr.mom", | 93 | "wss://nostr.mom", |
| @@ -1172,6 +1176,74 @@ bool BtfResolveMany(const std::vector<std::string>& btfAddrs, | |||
| 1172 | } | 1176 | } |
| 1173 | 1177 | ||
| 1174 | 1178 | ||
| 1179 | // ---- per-relay backoff ----------------------------------------------------- | ||
| 1180 | // | ||
| 1181 | // A relay that is down costs the whole discovery loop the full connect timeout, | ||
| 1182 | // every round, forever. relay.nostr.band went down and produced 1092 identical | ||
| 1183 | // error lines on the seed while adding ten seconds to every pass -- and the | ||
| 1184 | // loop is what discovers peers, so a dead relay was slowing down the live ones. | ||
| 1185 | // | ||
| 1186 | // Back off per relay instead: 30s after the first failure, doubling to a | ||
| 1187 | // fifteen-minute ceiling, cleared the moment it answers again. This changes | ||
| 1188 | // only when an attempt happens, never whether discovery is correct. | ||
| 1189 | struct CRelayBackoff | ||
| 1190 | { | ||
| 1191 | int64 nNextTry; | ||
| 1192 | int nFails; | ||
| 1193 | CRelayBackoff() : nNextTry(0), nFails(0) {} | ||
| 1194 | }; | ||
| 1195 | static map<string, CRelayBackoff> mapRelayBackoff; | ||
| 1196 | static CCriticalSection cs_relayBackoff; | ||
| 1197 | |||
| 1198 | static const int64 RELAY_BACKOFF_BASE_SECS = 30; | ||
| 1199 | static const int64 RELAY_BACKOFF_MAX_SECS = 15 * 60; | ||
| 1200 | |||
| 1201 | static bool RelayDueForRetry(const string& relay) | ||
| 1202 | { | ||
| 1203 | CRITICAL_BLOCK(cs_relayBackoff) | ||
| 1204 | { | ||
| 1205 | map<string, CRelayBackoff>::iterator it = mapRelayBackoff.find(relay); | ||
| 1206 | if (it == mapRelayBackoff.end()) | ||
| 1207 | return true; | ||
| 1208 | return GetTime() >= it->second.nNextTry; | ||
| 1209 | } | ||
| 1210 | return true; | ||
| 1211 | } | ||
| 1212 | |||
| 1213 | static void RelayNoteFailure(const string& relay) | ||
| 1214 | { | ||
| 1215 | CRITICAL_BLOCK(cs_relayBackoff) | ||
| 1216 | { | ||
| 1217 | CRelayBackoff& b = mapRelayBackoff[relay]; | ||
| 1218 | b.nFails++; | ||
| 1219 | int64 nWait = RELAY_BACKOFF_BASE_SECS; | ||
| 1220 | for (int i = 1; i < b.nFails && nWait < RELAY_BACKOFF_MAX_SECS; i++) | ||
| 1221 | nWait *= 2; | ||
| 1222 | if (nWait > RELAY_BACKOFF_MAX_SECS) | ||
| 1223 | nWait = RELAY_BACKOFF_MAX_SECS; | ||
| 1224 | b.nNextTry = GetTime() + nWait; | ||
| 1225 | // Only on the way in, so a relay that stays down says this once per | ||
| 1226 | // backoff step rather than once per pass. | ||
| 1227 | LogPrint("nostr", "Nostr: %s unreachable (%d in a row), not retrying for %ds\n", | ||
| 1228 | relay.c_str(), b.nFails, (int)nWait); | ||
| 1229 | } | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | static void RelayNoteSuccess(const string& relay) | ||
| 1233 | { | ||
| 1234 | CRITICAL_BLOCK(cs_relayBackoff) | ||
| 1235 | { | ||
| 1236 | map<string, CRelayBackoff>::iterator it = mapRelayBackoff.find(relay); | ||
| 1237 | if (it != mapRelayBackoff.end()) | ||
| 1238 | { | ||
| 1239 | if (it->second.nFails > 0) | ||
| 1240 | LogPrint("nostr", "Nostr: %s answering again after %d failure(s)\n", | ||
| 1241 | relay.c_str(), it->second.nFails); | ||
| 1242 | mapRelayBackoff.erase(it); | ||
| 1243 | } | ||
| 1244 | } | ||
| 1245 | } | ||
| 1246 | |||
| 1175 | // Connect to a relay: publish our .btf descriptor and collect relay data. | 1247 | // Connect to a relay: publish our .btf descriptor and collect relay data. |
| 1176 | static bool SeedFromRelay(CNostrKey& key, const string& relay) | 1248 | static bool SeedFromRelay(CNostrKey& key, const string& relay) |
| 1177 | { | 1249 | { |
| @@ -1653,9 +1725,14 @@ void ThreadNostrSeed(void* parg) | |||
| 1653 | for (int i = 0; i < nNostrRelays; i++) | 1725 | for (int i = 0; i < nNostrRelays; i++) |
| 1654 | { | 1726 | { |
| 1655 | if (fShutdown) return; | 1727 | if (fShutdown) return; |
| 1728 | if (!RelayDueForRetry(pszNostrRelays[i])) | ||
| 1729 | continue; | ||
| 1656 | try | 1730 | try |
| 1657 | { | 1731 | { |
| 1658 | SeedFromRelay(key, pszNostrRelays[i]); | 1732 | if (SeedFromRelay(key, pszNostrRelays[i])) |
| 1733 | RelayNoteSuccess(pszNostrRelays[i]); | ||
| 1734 | else | ||
| 1735 | RelayNoteFailure(pszNostrRelays[i]); | ||
| 1659 | } | 1736 | } |
| 1660 | CATCH_PRINT_EXCEPTION("SeedFromRelay") | 1737 | CATCH_PRINT_EXCEPTION("SeedFromRelay") |
| 1661 | } | 1738 | } |